web-dev-qa-db-ja.com

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

ユニットテスト用のユーザーを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', '[email protected]', '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) 

ありがとう。

66
thebossman

動作しないコード:

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')
93
Pedro M Duarte

より簡単な方法は force_login 、Django 1.9の新機能。

force_login(user, backend=None)

例えば:

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

_Django.contrib.sessions_が_INSTALLED_APPS_に追加されていることを確認してください。これは、client.login()がそれをチェックし、そうでない場合は常にfalseを返すためです。

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

5
e-satis

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

from Django.test import TransactionTestCase, Client

class UserHistoryTest(TransactionTestCase):
    self.user = User.objects.create(username='admin', password='pass@123', email='[email protected]')
    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)

このテストケースはうまくいきました。

4
Muthuvel
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)
0
aravind allu