Trouble with Test After Introducing django-axes
Source: Dev.to
Background
What is django-axes?
django-axes is a Django package that monitors login attempts and locks out users based on authentication settings. It helps prevent brute‑force attacks.
Why I used django-axes
I was working on a collaborative project to develop a small app with a login feature. To prevent brute‑force attacks, we wanted to limit the number of login attempts, so we decided to introduce django-axes.
Issue
After implementing django-axes, I ran all tests. Many tests that previously passed started failing. The failures were all related to login functionality because the tests did not include a request object.
When tests use client.login (as shown below), the user is authenticated without an HTTP request. However, django-axes determines whether a user is authenticated by inspecting the request, causing the failures.
Failing pattern (using client.login)
self.user = User.objects.create_user(
username="login_user",
email="login@example.com",
password="LoginPass123",
)
self.client.login(email="login@example.com", password="LoginPass123")
Working pattern (using client.post)
self.user = User.objects.create_user(
username="login_user",
email="login@example.com",
password="LoginPass123",
)
self.client.post(
self.login_url,
{"email": "login@example.com", "password": "LoginPass123"},
REMOTE_ADDR="192.168.1.1",
)
Solutions
I found two practical ways to resolve the issue.
1. Disable django-axes in tests
Set AXES_ENABLE = False in your test settings to disable django-axes checks during testing.
When you need to test features related to django-axes, re‑enable it with AXES_ENABLE = True.
Disabling Axes components in tests
This approach lets you limit django-axes behavior only to the tests that actually need it.
2. Use force_login()
force_login() bypasses the authentication process that django-axes hooks into. For tests that are not directly related to login verification, it is reasonable to use force_login() instead of client.login().
Working pattern (using force_login)
self.user = User.objects.create_user(
username="login_user",
email="login@example.com",
password="LoginPass123",
)
self.client.force_login(self.user)
As mentioned earlier, using client.post() also works because it includes a request.
Conclusion
django-axes is a very useful package for enhancing application security. However, when introducing it, we need to be careful about how authentication is handled in tests. Depending on the app architecture and testing strategy, choose the most appropriate solution—either disabling django-axes in tests or using force_login()/client.post() for authentication.
I hope this helps anyone facing similar issues.