Как исправить метод, чтобы избежать вызова базы данных - PullRequest
0 голосов
/ 25 апреля 2019

В целях обучения я пытаюсь написать тест, который исправляет функцию authenticate Джанго, чтобы избежать попадания в базу данных. Код, который я написал, не работает, и я не понимаю, почему. Я просмотрел сеть, но многое из того, что я прочитал, сбивает с толку. Любая помощь будет оценена.

Я использую Django, DRF, pytest, pytest-django и pytest-mock.

from django.contrib.auth import authenticate
from rest_framework.test import APIRequestFactory

def test_authenticate(mocker, user_factory):
    user = user_factory.build()

    mocker.patch('django.contrib.auth.authenticate', return_value=user)

    factory = APIRequestFactory()
    request = factory.get('/')

    data = {
        'username': user.email,
        'password': 'testpassword',
    }

    assert user == authenticate(request=request, **data)

В приведенном выше коде user_factory взято из conftest.py, и мы можем предположить, что он работает как ожидалось.

Я получаю ошибку:

E       Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.        

Опять же, я хочу избежать пометки теста для доступа к БД. Вместо этого я хочу иметь возможность высмеивать authenticate и контролировать его возвращаемое значение.

1 Ответ

1 голос
/ 26 апреля 2019

Правило № 1 для исправления: Ваше первое предположение о том, что вы должны исправлять, всегда неверно.
Правило № 2 для исправления: не исправляйте где-то IS , но исправляйте где-то Будет проверяться во время выполнения.

Вы импортировали authenticate и добавили его в пространство имен как authenticate.При исправлении патчер импортировал django.contrib.auth.authenticate в пространство имен и затем издевался над ним.Позже вы называете authenticate, оригинальную версию, которую вы импортировали в начале, а не ложную версию, которую патчер импортировал для вас.

Импортируя только django.contrib.auth и затем исправляя django.contrib.auth.authenticate, патчер «пробирается» в его смоделированную authenticate в django.contrib.auth.
Если вы затем делаете утверждение с помощью user == django.contrib.auth.authenticate, pythonбудет искать authenticate в django.contrib.auth и вместо этого найдет макет.

Тайна классического исправления: https://docs.python.org/3/library/unittest.mock.html#where-to-patch

...