Где издеваться над тестированием представления Django, которое вызывает службу?

Это Django 1.6.8, Python 2.7 и библиотека mock.

У меня есть представление, которое вызывает удаленную службу с использованием пены для сбора налоговой информации (это упрощенная версия):

def sales_tax(self, bundle_slug):
    bundle = get_object_or_404(Bundle, slug=bundle_slug,
                                active=True)

    cloud = TaxCloud(TAXCLOUD_API_ID, TAXCLOUD_API_KEY)
    origin = Address('origin address')
    destination = Address('customer address')
    cart_item = CartItem(bundle.sku, TAXCLOUD_TIC_ONLINE_GAMES,
                        bundle.price, 1)

    try:
        rate_info = cloud.get_rate(origin, destination,
                                    [cart_item],
                                    str(customer.id))

        sales_tax = Decimal(rate_info['sales_tax'])

        response = {'salesTax': locale.currency(sales_tax),
                    'total':  locale.currency(bundle.price + sales_tax)}
    except TaxCloudException as tce:
        response = {
            'error': str(tce)
        }

Вот соответствующий код из класса TaxCloud:

from suds.client import Client
from suds import WebFault

class TaxCloud(object):

    def __init__(self, api_login_id, api_key):
        self.api_login_id = api_login_id
        self.api_key = api_key
        self.soap_url = 'https://api.taxcloud.net/1.0/TaxCloud.asmx'
        self.wsdl_url = 'https://api.taxcloud.net/1.0/?wsdl' 

        self.client = Client(url=self.wsdl_url, location=self.soap_url, faults=False)

    def get_rate(self, billing_address, origin_address, raw_cart_items, customer_id):
        address = self.convert_to_address(billing_address)
        origin = self.convert_to_address(origin_address)
        cart_items = self.convert_to_cart_list(raw_cart_items)

        response = self.client.service.Lookup(self.api_login_id,
                                              self.api_key, customer_id,
                                              self.cart_id(customer_id), cart_items,
                                              address, origin, True, None)

        if( response[1].ResponseType == 'Error' ):
            raise TaxCloudException(response[1].Messages[0][0].Message)

        return {
            'sales_tax': str(response[1].CartItemsResponse[0][0].TaxAmount),
            'cart_id': response[1].CartID
        }

В моем тесте на представление я не хочу вызывать удаленную службу. Используя этот пример фиктивного клиента, я создал тупой фиктивный класс (мой ClientMock точно соответствует примеру в этом ответе) :

class TaxCloudServiceClientMock(ClientMock):
    """
    Mock object that implements remote side services.
    """

    def Lookup(cls, api_id, api, customer_id, cart_id, cart_items,
               address, origin, flag, setting):
        """
        Stub for remote service.
        """
        return """(200, (LookupRsp){
               ResponseType = "OK"
               Messages = ""
               CartID = "82cabf35faf66d8b197c7040a9f7382b3f61573fc043d73717"
               CartItemsResponse =
                  (ArrayOfCartItemResponse){
                     CartItemResponse[] =
                        (CartItemResponse){
                           CartItemIndex = 1
                           TaxAmount = 0.10875
                        },
                  }
                })"""

В своем тесте я пытаюсь @patch использовать Client в классе TaxCloud:

@patch('sales.TaxCloud.Client', new=TaxCloudServiceClientMock)
def test_can_retrieve_sales_tax(self):
    from django.core.urlresolvers import reverse

    tax_url = reverse('sales_tax', kwargs={'bundle_slug': self.bundle.slug})
    self.client.login(username=self.user.username, password='testpassword')

    response = self.client.get(tax_url, {'address1': '1234 Blah St',
                                        'city': 'Some City',
                                        'state': 'OH',
                                        'zipcode': '12345',
                                        'country': 'US'},
        HTTP_X_REQUESTED_WITH='XMLHttpRequest')

    self.assertEqual(response.status_code, 200)

Однако удаленный вызов все еще выполняется. На основе "Где издеваться" документации, я правильно нацеливаю sales.TaxCloud.Client вместо suds.client.Client.

Что могло быть причиной игнорирования / обхода патча?


person Melissa Avery-Weir    schedule 20.05.2015    source источник
comment
Я не эксперт по Django, но предполагаю, что объект TaxCloud создается не во время запроса, а во время инициализации службы django. Вам следует попробовать patch sales.TaxCloud.Client.service.Lookup вместо этого и использовать return_value вместо вашего собственного нового макета.   -  person Michele d'Amico    schedule 29.05.2015
comment
@melissa вы нашли решение для этого?   -  person cph2117    schedule 28.04.2017
comment
@ cph2117 К сожалению, нет. Мы смогли просто имитировать вызовы других сервисов, используя метод, который я описал выше, но не этот.   -  person Melissa Avery-Weir    schedule 07.05.2017