Не могу понять, почему мой тест входа в систему 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)