LoginSignup
0
0

More than 1 year has passed since last update.

Django: 別 Middleware に依存している Middleware をテストする

Last updated at Posted at 2020-03-18

概要

自作の 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する

参照

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0