djangoテスト-ログイン状態について
5360 ワード
djangoのテスト中にログインが必要な場合がよくあります.また,登録は通常のアカウントパスワード登録とoauth方式に分けて登録する.登録は面倒なことですが、多くの場合、私たちは一定の方法でこの部分を迂回することができます.この手順を行う前に、djangoがリクエストを送信する必要があるユニットテストスキームについて簡単に説明します.
djangoでrequestの送信を行うにはいくつかの方法がありますが、ここでは簡単に列挙します. TestCase下のClientを使用して要求 を行う. RequestFactoryを使用してrequestを構築するテスト 最も簡単なrequestsライブラリを使用してユニットテスト(比較的少ない) を行う. django-rest-frameworkを導入する場合、ApiTestCaseを使用してユニットテストを行うこともでき、Clientにはパッケージ を追加することができます.それ以外にもいくつかのテスト方法があります. は省略します.
djangoプロジェクトに登録されているミドルウェアをすべて遮断する暴力的な方法があります.これは良いスキームではありませんが、ログイン状態を取得する必要のないビュー関数のテストを短く解決できます.djangoにはデフォルトのユーザー認証ミドルウェアがあります.
pythonには非常に使いやすいテストフレームワークmockがあり、非常に多くのテストスキームを提供することができます.例えば、さっきの操作では、ユニットテストの関数に
djangoのclientはログイン関数login(username,password)を提供し、簡単な場合、このlogin関数を使用してログインし、すべてのミドルウェアとビュー関数を正常に実行することができます.しかし、この関数には、パスワードを持たないユーザーもいれば、oauth 2のようなtokenのような方法でログインするユーザーもいます.
djangoにはこのような関数
最終的には、djangoの
上から,
テストリクエスト
djangoでrequestの送信を行うにはいくつかの方法がありますが、ここでは簡単に列挙します.
ログインの解決
シールドミドルウェア
djangoプロジェクトに登録されているミドルウェアをすべて遮断する暴力的な方法があります.これは良いスキームではありませんが、ログイン状態を取得する必要のないビュー関数のテストを短く解決できます.djangoにはデフォルトのユーザー認証ミドルウェアがあります.
django.contrib.auth.middleware.AuthenticationMiddleware
はsettings.pyのミドルウェア構成にコメントを削除します.他にログイン関連のミドルウェアがあれば、コメントも必要です.これで簡単なログインの問題を解決できますが、友好的なテスト方法ではありません.元のエンジニアリングコードを修正しました.mockとpatchの使用
pythonには非常に使いやすいテストフレームワークmockがあり、非常に多くのテストスキームを提供することができます.例えば、さっきの操作では、ユニットテストの関数に
@patch('django.contrib.auth.middleware.AuthenticationMiddleware', return_value=None)
の装飾器を加えることができ、settingsを修正する必要はありません.pyのコードは、ログインミドルウェアを迂回することもできます.しかし,ビュー関数でユーザがログインした情報を取得する必要があるという問題は依然として解決できない.プロアクティブログイン
djangoのclientはログイン関数login(username,password)を提供し、簡単な場合、このlogin関数を使用してログインし、すべてのミドルウェアとビュー関数を正常に実行することができます.しかし、この関数には、パスワードを持たないユーザーもいれば、oauth 2のようなtokenのような方法でログインするユーザーもいます.
force_loginとforce_authenticate
djangoにはこのような関数
force_login(user, backend=None)
があり、django-rest-frameworkを使用するとforce_authenticate(user=None, token=None)
の関数もあります.クライアントを使用してログインすると、view関数でユーザーのログイン情報を取得できます.ただし、ミドルウェアではログイン状態を取得できないという問題があります.そしてforce_login関数はdjango 1にある.9まではありませんでした.get_user
最終的には、djangoの
django.contrib.auth.middleware.AuthenticationMiddleware
の論理を見ることができます.そこから猫が飽きてきた.class AuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
assert hasattr(request, 'session'), (
"The Django authentication middleware requires session middleware "
"to be installed. Edit your MIDDLEWARE%s setting to insert "
"'django.contrib.sessions.middleware.SessionMiddleware' before "
"'django.contrib.auth.middleware.AuthenticationMiddleware'."
) % ("_CLASSES" if settings.MIDDLEWARE is None else "")
request.user = SimpleLazyObject(lambda: get_user(request))
get_user
の関数があり、ソースコードは以下の通りです.def get_user(request):
if not hasattr(request, '_cached_user'):
request._cached_user = auth.get_user(request)
return request._cached_user
上から,
get_user
関数は実はミドルウェアがユーザを取得する論理であり,mockがこの関数を落とせばよいことがわかる.@patch('django.contrib.auth.middleware.get_user', return_value=User.objects.first())
ユーザモデルをpatchのreturn_に注入すればvalueの中に行けばいいです.ミドルウェアとview関数のログイン状態の問題を解決した.