Не могу понять, почему мой тест входа в систему DRF не работает так, как ожидалось

У меня есть следующий тестовый пример:

class CustomUserViewSetTests(APITestCase):
    @classmethod
    def setUpTestData(cls):
        cls.user = get_user_model().objects.create(
            email="test@email.com", password="testpass123"
        )

    def test_login_with_correct_data(self):
        url = reverse("knox_login")
        resp = self.client.post(
            url,
            data={
                "email": "test@email.com",
                "password": "testpass123",
            },
            format="json",
        )
        respJson = resp.json()
        self.assertEqual(resp.status_code, status.HTTP_200_OK)

Тест всегда проваливается, поскольку "resp" имеет код состояния 400 с телом {'non_field_errors': ['Unable to log in with provided credentials.']}.

Когда я проверяю тестовую базу данных через get_user_model().objects.all(), я вижу, что пользователь существует.

Кроме того, когда я вызываю url через Postman, я получаю код состояния 200 с токеном и данными пользователя, возвращаемыми в body.

Проблема в том, что вы используете objects.create(). Это нормально, если вы хотите создать Car, Item или Thing без паролей. Однако для модели User, поскольку она работает с хэшированием паролей, вы должны использовать ее специальный метод .create_user().

Ваш метод create записывает 'testpass123' в базу данных в виде необработанной строки. Но ваша логика входа сначала хэширует эту строку, а затем пытается войти в систему. Затем вход не удается, потому что он пытается сопоставить необработанный пароль из базы данных с хэшем пароля формы входа.

class CustomUserViewSetTests(APITestCase):
    @classmethod
    def setUpTestData(cls):
        # Create a user with a hashed password
        cls.user = get_user_model().objects.create_user(
            email="test@email.com", password="testpass123"
        )

При использовании метода .create_user() он принимает необработанную строку пароля, хэширует ее и сохраняет хэш в базе данных. При последующем входе в систему применяется та же логика. Пользователь вводит необработанный пароль, он хешируется, а затем хеш сравнивается с сохраненным хешем из базы данных.

Мой ответ применим только в том случае, если используемая вами модель пользователя наследуется от модели django User (django.contrib.auth)

Вернуться на верх