iconfinder / pyvat

VAT validation for Python
Other
66 stars 29 forks source link

VIES registry mocking #3

Open kdeldycke opened 9 years ago

kdeldycke commented 9 years ago

Unittests might fail if the VIES registry API is down. This happened to me in the last few weeks.

To prevent this failure, I mocked registries responses with the code:

import unittest
import arrow
from httmock import all_requests, response, HTTMock
try:
    from lxml import etree
except ImportError:
    from xml.etree import ElementTree as etree
from pyvat import check_vat_number, is_vat_number_format_valid

class TestVIES(unittest.TestCase):

    @all_requests
    def mock_registry_response(self, url, request):
        """ Mock VIES registry responses. """
        # Parse request
        soap_query = etree.fromstring(request.body)
        VAT_NS = '{urn:ec.europa.eu:taxud:vies:services:checkVat:types}'
        country_code = soap_query.find('.//{}countryCode'.format(VAT_NS)).text
        vat_number = soap_query.find('.//{}vatNumber'.format(VAT_NS)).text

        # Check VAT number
        assert is_vat_number_format_valid(vat_number, country_code) is True

        # Normalize parsed values
        country_code = country_code.strip().upper()
        vat_number = ''.join([c for c in vat_number if c.isalnum()]).upper()

        # Build-up response
        request_date = arrow.now().format('YYYY-MM-DDZZ')
        company_name = 'ICONFINDER ApS'
        company_address = 'Pilestr\xe6de 43 2\n1112 K\xf8benhavn K'
        content = \
            '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/' \
            'envelope/"><soap:Body><checkVatResponse xmlns="urn:ec.europ' \
            'a.eu:taxud:vies:services:checkVat:types"><countryCode>{}</c' \
            'ountryCode><vatNumber>{}</vatNumber><requestDate>{}</reques' \
            'tDate><valid>true</valid><name>{}</name><address>{}</addres' \
            's></checkVatResponse></soap:Body></soap:Envelope>'.format(
                country_code, vat_number, request_date, company_name,
                company_address)
        headers = {'Content-Type': 'text/xml'}
        return response(200, content, headers, None, 5, request)

    def test_vies_response_parsing(self):
        with HTTMock(self.mock_registry_response):
            results = check_vat_number('DK 33 77 94 37', 'DK')
            self.assertEqual(results.business_name, 'ICONFINDER ApS')
            self.assertEqual(
                results.business_address,
                'Pilestr\xe6de 43 2\n1112 K\xf8benhavn K')

Feel free to reuse it in pyvat if appropriate.

nickbruun commented 9 years ago

I like the general idea, but given that we're dealing with a public institution here (who are notorious for breaking things at random), I'm uncertain of whether or not not testing against them every time is a good idea.

kdeldycke commented 9 years ago

Maybe we can add both tests:

  1. The mocked one above which is testing pyvat XML parsing.
  2. The non-mocked one currently upstream which is testing that the live API is still returning the response format we expect.

But make the first test fatal and the second one optional.