如何使用unittest.mock调试修补方法

ali*_*s51 3 python django django-testing python-mock python-unittest

我有以下(简化的)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)
Run Code Online (Sandbox Code Playgroud)

我想测试该mailgun_validate_email函数是否被调用:

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)
 
Run Code Online (Sandbox Code Playgroud)

我确信测试调用如控制台中显示的mailgun_validate_email那样。print('Function called')但是我收到一个断言错误,该错误mock.called是False.

我哪里出错了/我该如何调试?

************更新*******************

当在与视图相同的模块中修补函数时,出现以下错误:

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)
Run Code Online (Sandbox Code Playgroud)

结果是:

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
Run Code Online (Sandbox Code Playgroud)

aar*_*ron 6

  1. 如果您from myapp import mailgun_validate_email这样做了check_existing_contacts,那么您需要修补该模块中的引用而不是myapp.
    例如,如果导入位于 myapp/views.py 中,则 patch myapp.views.mailgun_validate_email。
  2. 视图需要返回一个实例或其HttpResponse子类之一,因为mailgun_validate_email您直接返回return mailgun_validate_email(...).
# @patch('myapp.mailgun_validate_email')                                     # Change this
@patch('myapp.views.mailgun_validate_email', return_value=JsonResponse({}))  # to this
Run Code Online (Sandbox Code Playgroud)