2017-03-23 62 views
2

我已經編碼在1.10 style我的自定義Django的中間件,與此類似:不使用Django的測試自定義Django的中間件

class MyMiddleware(object): 
    def __init__(self, get_response): 
     self.get_response = get_response 
     # some initialization stuff here 

    def __call__(self, request): 
     # Code executed before view functions are called. 
     # Purpose of this middeware is to add new attribute to request 

     # In brief: 
     request.new_attribute = some_function_returning_some_object() 
     response = self.get_response(request) 

     # Code to be executed for each request/response after 
     # the view is called. 

     return response 

注意,這個中間件正在威脅着作爲一個單獨的Python模塊,不屬於我的項目中的任何特定應用程序,但通過pip居住在外部並像其他任何軟件包一樣安裝。它本身不工作,但只有在Django應用程序中安裝。

它工作正常,但是,我想測試它。我到目前爲止已經取得是這樣的my_tests.py

from my_middleware_module import MyMiddleware 
# some @patches 
def test_mymiddleware(): 
    request = Mock() 
    assert hasattr(request, 'new_attribute') is False # passes obviously 
    # CALL MIDDLEWARE ON REQUEST HERE 
    assert hasattr(request, 'new_attribute') is True # I want it to pass 

我不知道如何調用中間件上request變量進行修改。如果我使用類似功能的中間件風格,我認爲它會容易得多,但是如果我堅持我擁有的和我應該編寫測試而不修改中間件,會怎麼樣呢?

回答

3

問題是你既沒有調用MyMiddleware的構造函數也沒有調用MyMiddleware對象的實例調用__call__魔術方法。

有很多方法可以測試您所描述的行爲,我覺得這個:

首先,我稍微修改你的例子是自包含:

class MyMiddleware(object): 
    def __init__(self, get_response): 
     self.get_response = get_response 

    def __call__(self, request): 
     request.new_attribute = some_function_returning_some_object() 
     import ipdb; ipdb.set_trace() 
     response = self.get_response(request) 
     return response 

def some_function_returning_some_object(): 
    return 'whatever' 

接下來,我創建測試通過實際創建中間件對象並調用新創建的對象,因爲它是一個功能(讓__call__運行)

from mock import patch, Mock 
from middle import MyMiddleware 
import unittest 


class TestMiddleware(unittest.TestCase): 

    @patch('middle.MyMiddleware') 
    def test_init(self, my_middleware_mock): 
     my_middleware = MyMiddleware('response') 
     assert(my_middleware.get_response) == 'response' 

    def test_mymiddleware(self): 
     request = Mock() 
     my_middleware = MyMiddleware(Mock()) 
     # CALL MIDDLEWARE ON REQUEST HERE 
     my_middleware(request) 
     assert request.new_attribute == 'whatever' 

在這裏有一些有用的鏈接:在另一個SO問題__call__和__init__之間