alias51
alias51

Reputation: 8608

How to debug patched method with unittest.mock

I have the following (simplified) FBV:

def check_existing_contacts(request):
    if request.is_ajax and request.method == "GET":
        print('Function called')
        return mailgun_validate_email(request)
    return JsonResponse({"error": "Incorrect AJAX / GET request."}, status=400)

I want to test that the mailgun_validate_email function is called:

class TestCheckExistingContacts(TestCase):

    @patch('myapp.mailgun_validate_email')
    def test_new_contact(self, mock):
        client = Client()
        client.get('/check/', HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertTrue(mock.called)
 

I am certain the test calls mailgun_validate_email as the print('Function called') displays in the console. However I get an assertion error that the mock.called is False.

Where am I going wrong / how can I debug this?

************ UPDATE *******************

When patching the function in the same module as the view, I get the following error:

class TestCheckExistingContacts(TestCase):

    @patch('[path to views.py with check_existing_contacts].mailgun_validate_email')
    def test_new_contact(self, mock):
        client = Client()
        client.get('/check/', HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertTrue(mock.called)

Results in:

Failure
Traceback (most recent call last):
  File "\tests\test_utils.py", line 123, in test_new_contact
    response = self.client.get('/validate/',
  File "\.venv\lib\site-packages\django\test\client.py", line 518, in get
    response = super().get(path, data=data, secure=secure, **extra)
  File "\.venv\lib\site-packages\django\test\client.py", line 344, in get
    return self.generic('GET', path, secure=secure, **{
  File "\.venv\lib\site-packages\django\test\client.py", line 421, in generic
    return self.request(**r)
  File "\.venv\lib\site-packages\django\test\client.py", line 496, in request
    raise exc_value
  File "\.venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "\.venv\lib\site-packages\django\utils\deprecation.py", line 96, in __call__
    response = self.process_response(request, response)
  File "\.venv\lib\site-packages\django\contrib\sessions\middleware.py", line 45, in process_response
    patch_vary_headers(response, ('Cookie',))
  File "\.venv\lib\site-packages\django\utils\cache.py", line 267, in patch_vary_headers
    vary_headers = cc_delim_re.split(response['Vary'])
TypeError: expected string or bytes-like object

Upvotes: 3

Views: 2085

Answers (1)

aaron
aaron

Reputation: 43103

  1. If you did from myapp import mailgun_validate_email for check_existing_contacts, then you need to patch the reference in that module instead of myapp.
    E.g. if the import is in myapp/views.py, then patch myapp.views.mailgun_validate_email.
  2. The view needs to return an instance of HttpResponse or one of its subclasses, same for mailgun_validate_email since you directly return mailgun_validate_email(...).
# @patch('myapp.mailgun_validate_email')                                     # Change this
@patch('myapp.views.mailgun_validate_email', return_value=JsonResponse({}))  # to this

Upvotes: 6

Related Questions