Как имитировать патч для метода Serializer.is_valid () при модульном тестировании в Django Rest Framework - PullRequest
1 голос
/ 27 мая 2020

Я хочу иметь возможность модульного тестирования представления без подключения к базе данных, я могу имитировать исправление метода User.save (), но не знаю, как правильно исправить serializer.is_valid (). Похоже, что метод is_valid требует подключения к базе данных для проверки полей или чего-то в этом роде. Есть ли способ сделать это?

Я использую 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

Ответы [ 2 ]

0 голосов
/ 04 сентября 2020

Если вы тестируете метод is_valid(), вам следует исправить ту часть метода, которая предназначена для доступа к базе данных, чтобы тест не стал слишком дорогим (поскольку доступ к базе данных требует времени и ресурсов). Например, здесь я проверил, что мой сериализатор выдает правильные ошибки при отсутствии полей:

mocker.patch('rest_framework.validators.qs_exists', return_value=True)
        with pytest.raises(ValidationError):
            serializer.is_valid(raise_exception=True)
0 голосов
/ 27 мая 2020

Вы можете попробовать добавить в тест @ pytest.mark.django_db или исправить упомянутый метод следующим образом: mocker.patch("project.views.RegistrationSerializer.is_valid")

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...