概要
自作の Middleware を試験したいけど、別の Middleware に依存しているケースの対処法です。
どういうケース?
Middleware をテストする場合、
Middleware のインスタンスを作成し、process_request
メソッドを呼ぶのがメジャーなようです。
参照: Unit Testing Django Middleware - Adam Donaghy - Medium
※追記
嘘でした。Middleware の実装で process_request
関数の実装をしているケース(古めの実装)でのみ有効な話でした。
Middleware のクラスからインスタンスを作成し、インスタンスに対して mock を渡して実行でよさそうです。(かなりシンプル)
python - Testing custom Django middleware without using Django itself - Stack Overflow
しかし、別の Middleware で何かしらの処理を行っていることを前提にしている Middleware について、上記の方法では対応できません。
例えば、認証情報に係る処理を行う Middleware の場合、セッション関連のミドルウェアなどを経由していないと request.user
参照時に user
attributeが存在せず例外が発生することなどが考えられます。
対処
-
self.client.get()
で実行します (View を試験するのと同じように) - Middleware が下の層を呼び出す
get_response()
を適当なMockに差し替えます- ※クラスインスタンスが持つ
get_response()
は__init__
で注入するものになっているので、__init__
を適当なメソッドにすり替える必要があります。
- ※クラスインスタンスが持つ
サンプル
Middleware
class SampleMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# いろいろやる
return self.get_response(request)
テスト
from unittest import mock
from django.http import HttpResponse
from django.test import TestCase
def fake_init(self, _):
def get_response(request):
return HttpResponse()
self.get_response = get_response
class SampleMiddlewareTest(TestCase):
def setUp(self):
self.mock_init = mock.patch.object(
AuthMiddleware, "__init__", fake_init
).start()
self.addCleanup(mock.patch.stopall)
def test_いろいろテスト(self):
# リクエストする
self.client.get("/")
# assertする
参照
-
Mocking complicated
__init__
in Python - George Shuklin - Medium-
__init__
を lambda で何もしない関数を注入しているサンプルを参考にしました。
-