<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: harubo</title>
    <description>The latest articles on Forem by harubo (@harumq).</description>
    <link>https://forem.com/harumq</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3682329%2F60c52dcc-fc96-4516-8e28-510257f236ff.png</url>
      <title>Forem: harubo</title>
      <link>https://forem.com/harumq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/harumq"/>
    <language>en</language>
    <item>
      <title>Trouble with Test After Introducing django-axes</title>
      <dc:creator>harubo</dc:creator>
      <pubDate>Sun, 04 Jan 2026 08:33:02 +0000</pubDate>
      <link>https://forem.com/harumq/trouble-with-test-after-introducing-django-axes-233i</link>
      <guid>https://forem.com/harumq/trouble-with-test-after-introducing-django-axes-233i</guid>
      <description>&lt;p&gt;When I introduced django-axes to app with a login feature, many tests which use client.login started failing. In this article, I explain why this happened and how I solved the problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What is django-axes?&lt;br&gt;
django-axes is a Django package that monitors login attempts and to lock out users based on authentication setting.It helps prevent brute-force attacks.&lt;br&gt;
(&lt;a href="https://django-axes.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;Official document&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why I used django-axes&lt;br&gt;
I was working on collaborative project to develop a small app with a login feature. &lt;br&gt;
To prevent brute-force attacks, we wanted to limit the number of login attempts, so we decided to introduce django-axes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Issue
&lt;/h3&gt;

&lt;p&gt;After implementing of django-axes, I ran all tests. &lt;br&gt;
Many tests are failed, even though they had passed before introducing django-axes. &lt;/p&gt;

&lt;p&gt;After investigating the errors, I found that all failing tests were related to login functionality. The root cause was that test did not include a request object.&lt;/p&gt;

&lt;p&gt;When tests use client.login(as shown below), the user is authenticated without a HTTP request. However, django-axes determines whether a user is authenticated by inspecting the request. As a result, all tests using client.login failed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Failing pattern (using client.login)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;self.user = User.objects.create_user(
            username="login_user",
            email="login@example.com",
            password="LoginPass123",
        )

self.client.login(email="login@example.com", password="LoginPass123")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the other hand, test using client.post passed successfully because they include a HTTP request.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Working pattern (using client.post)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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",
            )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Solutions
&lt;/h3&gt;

&lt;p&gt;I found two practical solutions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Disable django-axes in tests using AXES_ENABLE
By setting AXES_ENABLE = False in test settings, you can disable django-axes checks during testing.
Of course, when testing features related to django-axes, you should enable it by setting AXES_ENABLE = True.
(&lt;a href="https://django-axes.readthedocs.io/en/latest/2_installation.html#:~:text=to%20misconfigured%20settings.-,Disabling%20Axes%20components%20in%20tests,-%EF%83%81" rel="noopener noreferrer"&gt;document&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach allows you to limit django-axes behavior only to tests that actually need it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using force_login()
If you use force_login(), Django skips the authentication process that django-axes hooks into.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There, when testing features not directly related to login verification, it is reasonable to use force_login() instead of client.login().&lt;br&gt;
(&lt;a href="https://docs.djangoproject.com/en/3.2/topics/testing/tools/#:~:text=correctly%20hashed%20password.-,force_login,-(user%2C)" rel="noopener noreferrer"&gt;document&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Working pattern (Using force_login)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;self.user = User.objects.create_user(
            username="login_user",
            email="login@example.com",
            password="LoginPass123",
        )

self.client.force_login(self.user)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned earlier, using client.post() also works because it includes a request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;django-axes is a very useful package for enhance application security. However, when introducing it, we need to be carful about how authentication is handled in tests. &lt;/p&gt;

&lt;p&gt;Depend on the app architecture, and testing strategy, we should choose the most appropriate solution.&lt;/p&gt;

&lt;p&gt;I hope this help anyone facing similar issues.&lt;/p&gt;

</description>
      <category>django</category>
      <category>testing</category>
      <category>security</category>
      <category>authentication</category>
    </item>
  </channel>
</rss>
