djangoテスト-ログイン状態について

5360 ワード

djangoのテスト中にログインが必要な場合がよくあります.また,登録は通常のアカウントパスワード登録とoauth方式に分けて登録する.登録は面倒なことですが、多くの場合、私たちは一定の方法でこの部分を迂回することができます.この手順を行う前に、djangoがリクエストを送信する必要があるユニットテストスキームについて簡単に説明します.

テストリクエスト


djangoでrequestの送信を行うにはいくつかの方法がありますが、ここでは簡単に列挙します.
  • TestCase下のClientを使用して要求
  • を行う.
  • RequestFactoryを使用してrequestを構築するテスト
  • 最も簡単なrequestsライブラリを使用してユニットテスト(比較的少ない)
  • を行う.
  • django-rest-frameworkを導入する場合、ApiTestCaseを使用してユニットテストを行うこともでき、Clientにはパッケージ
  • を追加することができます.
  • それ以外にもいくつかのテスト方法があります.
  • は省略します.

    ログインの解決


    シールドミドルウェア


    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関数のログイン状態の問題を解決した.