如何查看APIView是否调用了服务函数?
How to check if there was a call of service function from APIView?
我正在尝试在我的 API 中实现服务层。现在我正在尝试从 APIView 测试服务函数调用。当我发送带有名为 'test_view_calls_service' 的测试的 POST 请求时,我有一个 201 状态代码,这意味着我的作者已创建。此检查也通过了测试:
self.assertTrue(Author.objects.filter(**self.data).exists())
但是测试仍然没有从 APIView
中看到服务函数调用
views.py
class AuthorListApiView(APIView):
permission_classes = [permissions.IsAuthenticated]
class InputSerializer(serializers.Serializer):
name = serializers.CharField()
def post(self, request):
serializer = self.InputSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
create_author(**serializer.validated_data)
return Response(serializer.data, status=status.HTTP_201_CREATED)
services.py
def create_author(name: str) -> Author:
"""
Create a Author model object.
"""
author = Author(name=name)
author.full_clean()
author.save()
return author
test_view.py
from unittest import mock
from django.urls import reverse
from faker import Faker
from test_plus.test import TestCase as PlusTestCase
faker = Faker()
class AuthorListApiViewTest(PlusTestCase):
def setUp(self):
self.url = reverse('authors')
self.data = {
'name': faker.pystr(max_chars=20)
}
self.user = self.make_user('user')
def test_api_view_can_be_accessed(self):
self.client.get(self.url)
self.response_200
def test_api_view_can_create(self):
self.client.post(self.url, data=self.data)
self.response_201
@mock.patch('books.services.create_author')
def test_view_calls_service(self, service_mock):
with self.login(self.user):
response = self.client.post(self.url, data=self.data)
print(response.status_code)
self.assertTrue(Author.objects.filter(**self.data).exists()) <--- This check is also passed
service_mock.assert_called_once_with(**self.data)
断言错误:
Found 8 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..201
F.....
======================================================================
FAIL: test_view_calls_service
(books.tests.test_views.AuthorListApiViewTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "c:\users\user\appdata\local\programs\python\python38-
32\lib\unittest\mock.py", line 1342, in patched
return func(*newargs, **newkeywargs)
File "F:\DeepMind\books_api\books\tests\test_views.py", line 34, in
test_view_calls_service
service_mock.assert_called_once_with(**self.data)
File "c:\users\user\appdata\local\programs\python\python38-
32\lib\unittest\mock.py", line 918, in assert_called_once_with
raise AssertionError(msg)
AssertionError: Expected 'create_author' to be called once. Called 0 times.
----------------------------------------------------------------------
Ran 8 tests in 1.626s
FAILED (failures=1)
Destroying test database for alias 'default'...
你打错了模块。 create_author
应该在测试查找的地方而不是声明的地方打补丁。
# test_view.py
class AuthorListApiViewTest(PlusTestCase):
@mock.patch('books.views.create_author')
def test_view_calls_service(self, service_mock):
...
此外,在这里使用 patch 而不向 patch
函数传递任何参数将完全取代真正的 create_author
函数。如果您只想记录在将调用传递给实际函数时通过 create_author
函数传递的参数,您可以使用 patch
装饰器的 wraps
参数。
# test_view.py
class AuthorListApiViewTest(PlusTestCase):
@mock.patch('books.views.create_author', wraps=create_author)
def test_view_calls_service(self, service_mock):
...
进一步阅读
我正在尝试在我的 API 中实现服务层。现在我正在尝试从 APIView 测试服务函数调用。当我发送带有名为 'test_view_calls_service' 的测试的 POST 请求时,我有一个 201 状态代码,这意味着我的作者已创建。此检查也通过了测试:
self.assertTrue(Author.objects.filter(**self.data).exists())
但是测试仍然没有从 APIView
中看到服务函数调用views.py
class AuthorListApiView(APIView):
permission_classes = [permissions.IsAuthenticated]
class InputSerializer(serializers.Serializer):
name = serializers.CharField()
def post(self, request):
serializer = self.InputSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
create_author(**serializer.validated_data)
return Response(serializer.data, status=status.HTTP_201_CREATED)
services.py
def create_author(name: str) -> Author:
"""
Create a Author model object.
"""
author = Author(name=name)
author.full_clean()
author.save()
return author
test_view.py
from unittest import mock
from django.urls import reverse
from faker import Faker
from test_plus.test import TestCase as PlusTestCase
faker = Faker()
class AuthorListApiViewTest(PlusTestCase):
def setUp(self):
self.url = reverse('authors')
self.data = {
'name': faker.pystr(max_chars=20)
}
self.user = self.make_user('user')
def test_api_view_can_be_accessed(self):
self.client.get(self.url)
self.response_200
def test_api_view_can_create(self):
self.client.post(self.url, data=self.data)
self.response_201
@mock.patch('books.services.create_author')
def test_view_calls_service(self, service_mock):
with self.login(self.user):
response = self.client.post(self.url, data=self.data)
print(response.status_code)
self.assertTrue(Author.objects.filter(**self.data).exists()) <--- This check is also passed
service_mock.assert_called_once_with(**self.data)
断言错误:
Found 8 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..201
F.....
======================================================================
FAIL: test_view_calls_service
(books.tests.test_views.AuthorListApiViewTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "c:\users\user\appdata\local\programs\python\python38-
32\lib\unittest\mock.py", line 1342, in patched
return func(*newargs, **newkeywargs)
File "F:\DeepMind\books_api\books\tests\test_views.py", line 34, in
test_view_calls_service
service_mock.assert_called_once_with(**self.data)
File "c:\users\user\appdata\local\programs\python\python38-
32\lib\unittest\mock.py", line 918, in assert_called_once_with
raise AssertionError(msg)
AssertionError: Expected 'create_author' to be called once. Called 0 times.
----------------------------------------------------------------------
Ran 8 tests in 1.626s
FAILED (failures=1)
Destroying test database for alias 'default'...
你打错了模块。 create_author
应该在测试查找的地方而不是声明的地方打补丁。
# test_view.py
class AuthorListApiViewTest(PlusTestCase):
@mock.patch('books.views.create_author')
def test_view_calls_service(self, service_mock):
...
此外,在这里使用 patch 而不向 patch
函数传递任何参数将完全取代真正的 create_author
函数。如果您只想记录在将调用传递给实际函数时通过 create_author
函数传递的参数,您可以使用 patch
装饰器的 wraps
参数。
# test_view.py
class AuthorListApiViewTest(PlusTestCase):
@mock.patch('books.views.create_author', wraps=create_author)
def test_view_calls_service(self, service_mock):
...
进一步阅读