【发布时间】:2021-03-02 19:18:36
【问题描述】:
我正在编写一个与第三方 API 集成的基本 Django 应用程序。以下是所涉及文件的基本文件夹结构:
timecardsite/
__init__.py
tests/
__init__.py
tests.py
services.py
views.py
...
services.py 文件包含与第三方 API 直接交互的各种函数。它们通常会返回包含我需要在视图中使用的数据的字典。
在我的测试文件中,特别是在我测试视图的类中,我试图模拟其中一些服务函数的返回值,所以理想情况下它们甚至不会被调用(我测试服务函数直接在另一个类中):
tests.py
from unittest.mock import patch
from django.test import TestCase
import timecardsite.services as services
from timecardsite.models import Account
...
class ViewsTests(TestCase):
@patch('timecardsite.views.services.get_access_token')
@patch('timecardsite.views.services.get_account_info')
def test_auth_view_saves_tokens_and_account_info_to_db(self, mock_access, mock_account):
# Mock both get_access_token and get_account_info
code = generate_random_token()
access_token = generate_random_token()
refresh_token = generate_random_token()
account_id = generate_random_token(length=5)
name = 'Example name'
mock_access.return_value = {
'access_token': access_token,
'refresh_token': refresh_token
}
mock_account.return_value = {
'account_id': account_id,
'name': name
}
self.client.get(f'/auth/?code={code}')
self.assertEqual(Account.objects.count(), 1)
new_account = Account.objects.first()
self.assertEqual(new_account.account_id, account_id)
self.assertEqual(new_account.name, name)
self.assertEqual(new_account.access_token, access_token)
self.assertEqual(new_account.refresh_token, refresh_token)
调用这些函数的视图:
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
import timecardsite.services as services
from timecardsite.models import Account
def auth(request):
# capture code from url
code = request.GET.get('code')
if code:
# request tokens
tokens = services.get_access_token(code)
# request account info
account_info = services.get_account_info(tokens['access_token'])
# create Account object
account = Account(
account_id = account_info['account_id'],
access_token = tokens['access_token'],
refresh_token = tokens['refresh_token'],
name = account_info['name']
)
account.save()
return HttpResponseRedirect(reverse('dashboard'))
这是我得到的错误 - 很明显,模拟的服务函数正在被调用,并且失败了,因为它试图用我生成的假代码来访问实际的 API。
..........E
======================================================================
ERROR: test_auth_view_saves_tokens_and_account_info_to_db (timecardsite.tests.tests.ViewsTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/holden/.pyenv/versions/3.7.10/lib/python3.7/unittest/mock.py", line 1256, in patched
return func(*args, **keywargs)
File "/Users/holden/Projects/timesheet/timecardsite/tests/tests.py", line 193, in test_auth_view_saves_tokens_and_account_info_to_db
self.client.get(f'/auth/?code={code}')
File "/Users/holden/.pyenv/versions/timesheet/lib/python3.7/site-packages/django/test/client.py", line 739, in get
response = super().get(path, data=data, secure=secure, **extra)
File "/Users/holden/.pyenv/versions/timesheet/lib/python3.7/site-packages/django/test/client.py", line 395, in get
**extra,
File "/Users/holden/.pyenv/versions/timesheet/lib/python3.7/site-packages/django/test/client.py", line 470, in generic
return self.request(**r)
File "/Users/holden/.pyenv/versions/timesheet/lib/python3.7/site-packages/django/test/client.py", line 716, in request
self.check_exception(response)
File "/Users/holden/.pyenv/versions/timesheet/lib/python3.7/site-packages/django/test/client.py", line 577, in check_exception
raise exc_value
File "/Users/holden/.pyenv/versions/timesheet/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/Users/holden/.pyenv/versions/timesheet/lib/python3.7/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/holden/Projects/timesheet/timecardsite/views.py", line 19, in auth
account_info = services.get_account_info(tokens['access_token'])
KeyError: 'access_token'
----------------------------------------------------------------------
Ran 11 tests in 0.074s
如何成功模拟这些函数?
谢谢。
【问题讨论】:
标签: python django unit-testing mocking