Djangoのself.client.login(…)は単体テストでは機能しません


83

ユニットテスト用のユーザーを2つの方法で作成しました。

1)「auth.user」のフィクスチャを次のように作成します。

    { 
        "pk": 1, 
        "model": "auth.user", 
        "fields": { 
            "username": "homer", 
            "is_active": 1, 
            "password": 
"sha1$72cd3$4935449e2cd7efb8b3723fb9958fe3bb100a30f2", 
            ... 
        } 
    }

一見重要でない部分は省略しました。

2)setUp関数で「create_user」を使用します(ただし、すべてをフィクスチャクラスに保持したいのですが):

def setUp(self): 
       User.objects.create_user('homer', 'ho...@simpson.net', 'simpson') 

どちらの場合も、パスワードはシンプソンであることに注意してください。

この情報がテストデータベースに何度も正しく読み込まれていることを確認しました。User.objects.getを使用してUserオブジェクトを取得できます。「check_password」を使用して、パスワードが正しいことを確認できます。ユーザーはアクティブです。

それでも、常に、self.client.login(username = 'homer'、password = 'simpson')は失敗します。理由がわからない。私はこれに関連するすべてのインターネットの議論を読んだと思います。誰か助けてもらえますか?

私の単体テストのログインコードは次のようになります。

    login = self.client.login(username='homer', password='simpson') 
    self.assertTrue(login) 

ありがとう。


1
表示されたエラーメッセージは何ですか?
zs2020 2010

テストケースは、 'self.assertTrue(login)'の行で失敗します。login()関数はFalseを返します。
ボスマン2010

1
基本的に2番目のバリエーションをコピーして貼り付けましたが、Django1.3で動作します。インポートを含むコード全体を投稿できますか?
Liorsion 2011年

これは、私がアクセスしなくなったコードベースのどこかに埋もれています。問題に遭遇した場合は必ずフォローアップしますが、記録としては、以前のバージョンのDjangoを使用していました。1.0.2だと思います。
ボスマン2011年

回答:


120

動作しないコード:

from django.contrib.auth.models import User
from django.test import Client

user = User.objects.create(username='testuser', password='12345')

c = Client()
logged_in = c.login(username='testuser', password='12345')

なぜそれが機能しないのですか?

上記のスニペットでUserは、が作成されると、実際のパスワードハッシュはに設定されます12345。クライアントがloginメソッドを呼び出すと、password引数の値12345、がハッシュ関数を介して渡され、次のようになります。

hash('12345') = 'adkfh5lkad438....'

次に、これはデータベースに保存されているハッシュと比較され、クライアントはアクセスを拒否されます。 'adkfh5lkad438....' != '12345'

ソリューション

適切な方法は、set_password関数を呼び出すことです。この関数は、指定された文字列をハッシュ関数に渡し、結果をに格納しUser.passwordます。

さらに、呼び出した後set_password、更新されたUserオブジェクトをデータベースに保存する必要があります。

user = User.objects.create(username='testuser')
user.set_password('12345')
user.save()

c = Client()
logged_in = c.login(username='testuser', password='12345')

44
あなたは使用しUser.objects.create_superuser()User.objects.create_user()それはまさにこのset_password()呼び出しを実行します。
vdboor 2016

あなたが人をログインさせるときはどうですか
ロッキー

@vdboorコメントに追加する:ノートをDjangoの1.4もあるためということUser.objects.get_or_create()に必要な実行set_password()コールを
furins

51

より簡単な方法はforce_login、Django1.9の新機能であるを使用することです。

force_login(user, backend=None)

例えば:

class LoginView(TestCase):
    def setUp(self):
        self.client.force_login(User.objects.get_or_create(username='testuser')[0])

5

以下のように確認できますか?

from django.test import TransactionTestCase, Client

class UserHistoryTest(TransactionTestCase):
    self.user = User.objects.create(username='admin', password='pass@123', email='admin@admin.com')
    self.client = Client() # May be you have missed this line

    def test_history(self):
        self.client.login(username=self.user.username, password='pass@123')
        # get_history function having login_required decorator
        response = self.client.post(reverse('get_history'), {'user_id': self.user.id})
        self.assertEqual(response.status_code, 200)

このテストケースは私のために働いた。


5

チェックdjango.contrib.sessionsに追加されたINSTALLED_APPSので、client.login()それがあり、それがない場合は、常にfalseを返すことを確認:

https://docs.djangoproject.com/es/1.9/topics/http/sessions/#enabling-sessions


2
このために+1。でもとdjango.contrib.sessions.middleware.SessionMiddlewareミドルウェアclasssesであなたはまだdjango.test.Client経由でログインすることはできません。この答えを見つけるのに1週間かかります
生徒

0
from django.test import TestCase
from django.contrib.auth.models import User
from django.test import Client
class MyProfile(TestCase):
    @classmethod
    def setUpClass(self):
        self.username = 'dummy' + data + '@gmail.com'
        self.password = 'Dummy@123'
        user = User.objects.create(username=self.username)
        user.set_password(self.password)
        user.save()
        c = Client()
        self.client_object = c.login(username=self.username, password=self.password)
        self.content_type = "application/json"
        response = self.client_object.post('/api/my-profile/', content_type=self.content_type)

-3

まだこれをフォローしている人がいる場合は、ログインに成功するために、属性「is_staff」と「is_active」をTrueに保つ必要があると思います......

self.user = User.objects.create(username='testuser',password='pwd',is_active=1,is_staff=1)


4
これはうまくいきました........... self.user = User.objects.create(username = 'testuser'、password = '12345'、is_active = True、is_staff = True、is_superuser = True)self。 user.set_password( 'hello')self.user.save()user = authenticate(username = 'testuser'、password = 'hello')login = self.c.login(username = 'testuser'、password = 'hello' )self.assertTrue(login)
Arindam Roychowdhury 2012年

これはis_staff、一般に管理パネルへのアクセスが許可されるかどうかを定義するものとは関係ありません。ご覧のとおり、最初の投稿のデータにはすでにがis_active = 1あり、これはのデフォルトでもありますUser.objects.create()
jnns 2013年

1
@ arindamroychowdhury-うわー、それは実際に機能しました..(あなたのコメント、つまり)
Richard de Wit

1
バージョンの問題かもしれませんが、認証呼び出しをコメントアウトする必要がありました。それ以外は、あなたのコメントはチャンピオンのように機能しました!さらにテストを行ったところ、is_active、is_superuser、is_staffはすべて不要であることがわかりました。それを行ったのは、set_passwordの呼び出しでした。
dolphus333 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.