我希望能够在不连接到数据库的情况下对视图进行单元测试,我可以模拟修补User.save()方法,但不知道如何正确修补serializer.is_valid()。看来is_valid方法需要db连接来验证字段或类似的东西。有办法吗?
我正在使用django-pytest和pytest-mock
这是要测试的视图
class RegistrationViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet):
permission_classes = (AllowAny,)
serializer_class = RegistrationSerializer
def create(self, request):
user = request.data.get('user', {})
serializer = self.serializer_class(data=user)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
这是我的序列化器
class RegistrationSerializer(serializers.ModelSerializer):
"""Serializers registration request and creates a new user."""
password = serializers.CharField(
max_length=128,
min_length=8,
write_only=True # can not be read by the client
)
token = serializers.CharField(max_length=255, read_only=True)
class Meta:
model = User
fields = ['email', 'username', 'password', 'token']
def create(self, validated_data):
return User.objects.create_user(**validated_data)
到目前为止,这是我的视力测试
class TestRegistrationViewSet:
"""
Test cases for registrating user
"""
def test_register_user_success(self, rf, mocker):
url = reverse('registration-list')
data = {
"user": {
'username': 'user1',
'email': "email@cookie.com",
'password': 'user1pass'
}
}
request = rf.post(url, data=data, content_type='application/json')
mocker.patch.object(User, 'save')
response = RegistrationViewSet.as_view({'post': 'create'})(request).render()
assert response.status_code == status.HTTP_201_CREATED
这是我得到的错误回溯
repostery\authentication\views.py:21: in create
serializer.is_valid(raise_exception=True)
.venv\lib\site-packages\rest_framework\serializers.py:234: in is_valid
self._validated_data = self.run_validation(self.initial_data)
.venv\lib\site-packages\rest_framework\serializers.py:433: in run_validation
value = self.to_internal_value(data)
.venv\lib\site-packages\rest_framework\serializers.py:490: in to_internal_value
validated_value = field.run_validation(primitive_value)
.venv\lib\site-packages\rest_framework\fields.py:830: in run_validation
return super().run_validation(data)
.venv\lib\site-packages\rest_framework\fields.py:566: in run_validation
self.run_validators(value)
.venv\lib\site-packages\rest_framework\fields.py:588: in run_validators
validator(value, self)
.venv\lib\site-packages\rest_framework\validators.py:73: in __call__
if qs_exists(queryset):
.venv\lib\site-packages\rest_framework\validators.py:21: in qs_exists
return queryset.exists()
.venv\lib\site-packages\django\db\models\query.py:777: in exists
return self.query.has_results(using=self.db)
.venv\lib\site-packages\django\db\models\sql\query.py:538: in has_results
return compiler.has_results()
.venv\lib\site-packages\django\db\models\sql\compiler.py:1121: in has_results
return bool(self.execute_sql(SINGLE))
.venv\lib\site-packages\django\db\models\sql\compiler.py:1149: in execute_sql
cursor = self.connection.cursor()
.venv\lib\site-packages\django\utils\asyncio.py:26: in inner
return func(*args, **kwargs)
.venv\lib\site-packages\django\db\backends\base\base.py:260: in cursor
return self._cursor()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <django.db.backends.postgresql.base.DatabaseWrapper object at 0x00000218938FA670>, name = None
def _cursor(self, name=None):
> self.ensure_connection()
E RuntimeError: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
.venv\lib\site-packages\django\db\backends\base\base.py:236: RuntimeError
答案 0 :(得分:0)
您可以尝试将@ pytest.mark.django_db添加到测试中,或者可以像下面这样修补提到的方法:
mocker.patch("project.views.RegistrationSerializer.is_valid")
答案 1 :(得分:0)
如果要测试的是is_valid()
方法,则应修补该方法中打算访问数据库的部分,以免测试变得昂贵(因为访问数据库需要时间和资源)。例如,在这里我测试了当缺少字段时,我的序列化程序会引发正确的错误:
mocker.patch('rest_framework.validators.qs_exists', return_value=True)
with pytest.raises(ValidationError):
serializer.is_valid(raise_exception=True)