DjangoBrothers BLOG ✍️

2021/02/16

このエントリーをはてなブックマークに追加
Django ログイン DjangoRESTFramework テスト

DjangoやDRFのテストクライアントにヘッダーを設定する方法

DRFでSimple-JWTを使ってJWT認証できるようにした。

Simple-JWTを使うと、ヘッダーに Authorization: JWT <アクセストークン> を設定することでユーザー認証できるようになる。

テストを書く時に、このヘッダーの設定方法がわからなかったので調べた。

バージョン

  • Django 3.1.5
  • djangorestframework 3.12.2
  • pytest 6.2.2

うまくいかない例

はじめは、headersに設定してみたがうまくいかなかった。

headersでAuthorization設定

class TestClass:
  def test_hoge(self, client):
    res = client.get("/api/target/path/", headers={"Authorization": f"JWT {トークン}"})

うまくいった例

kwargs(可変長キーワード引数)にHTTP_ヘッダー名の形で指定したらうまくいった。

動いた

class TestClass:
  def test_hoge(self, client):
    res = client.get("/api/target/path/", HTTP_AUTHORIZATION=f"JWT {トークン}")

今回はpytestのclientフィクスチャを使ったけど、Django標準のテストクライアントでも同じ話のはず。

公式ドキュメントでは以下の箇所で言及されている。

DRFのAPIClientでヘッダー設定

DRFのAPIClientではcredentialsを使うことで同様のことができる模様。(動作未確認)

APIClientにヘッダー設定

client = APIClient()
client.credentials(HTTP_AUTHORIZATION=f"JWT {トークン")

テストコードでJWTトークンの取得

テストコードでJWTトークンを取得する方法もついでに書いておく。テストデータの生成にはfactoryboyを使っている。

Userファクトリー

class UserFactory(factory.django.DjangoModelFactory):

  password = factory.PostGenerationMethodCall("set_password", "testpass")

  class Meta:
    model = User

テストファイル

user = UserFactory()

res = client.post("/api/token/", data={"username": user.username, "password": "testpass"}, content_type="application/json")

token = res.json()["access"]

トークンを使わずログイン

そもそもトークンを使う必要はなくただログイン状態にできれば良い場合は、client.loginclient.force_loginを使った方が楽。

login、force_loginでログインさせる

client.login(username=user.username, password="testpass")

client.force_login(user=user)