2015-11-07 130 views
2

我正在使用python的unittest.mock在Django應用程序中執行一些測試。我想檢查一個類是否被調用,並且它的實例上的方法也被調用。模擬python單元測試中的類和類方法

例如,給定這個簡化的示例代碼:

# In project/app.py 
def do_something(): 
    obj = MyClass(name='bob') 
    return obj.my_method(num=10) 

而這個測試來檢查發生的事情:

# In tests/test_stuff.py 
@patch('project.app.MyClass') 
def test_it(self, my_class): 
    do_something() 
    my_class.assert_called_once_with(name='bob') 
    my_class.my_method.assert_called_once_with(num=10) 

試驗成功說my_class被調用,但是他說,my_class.my_method不調用。我知道我錯過了一些東西 - 嘲笑模擬課堂上的一種方法? - 但我不確定什麼或如何使它工作。

回答

2

你的第二個模擬斷言需要測試你是在實例調用my_method,而不是類本身。

調用模擬對象這樣,

my_class().my_method.assert_called_once_with(num=10) 
     ^^ 
+0

Doh!我花了很長時間看着我認爲我做錯了嘲笑,我錯過了那個愚蠢的錯誤!謝謝Jared。 –

1

如果my_method是一個類的方法這一行

my_class.my_method.assert_called_once_with(num=10) 

會工作。

是這樣嗎?

否則,如果my_method僅僅是一個正常的實例方法,那麼你就需要重構功能do_something來獲得實例變量obj

例如握住

def do_something(): 
    obj = MyClass(name='bob') 
    return obj, obj.my_method(num=10) 

# In tests/test_stuff.py 
@patch('project.app.MyClass') 
def test_it(self, my_class): 
    obj, _ = do_something() 
    my_class.assert_called_once_with(name='bob') 
    obj.my_method.assert_called_once_with(num=10) 
+0

謝謝安東尼。在某種程度上,這與Jared的回答有何不同? (我不是說它不是,我只是不明白就知道!) –

1

小重構建議爲你的單元測試,以幫助其他的實例方法你可能在你的測試遇到。而不是在每種方法中嘲笑你的課程,你可以在setUp方法中設置這一切。這樣,當班級嘲笑並從該班級創建模擬對象時,您現在可以根據需要多次使用該對象,測試班級中的所有方法。

爲了說明這一點,我將下面的例子放在一起。評論在線:

class MyTest(unittest.TestCase): 

    def setUp(self): 
     # patch the class 
     self.patcher = patch('your_module.MyClass') 
     self.my_class = self.patcher.start() 

     # create your mock object 
     self.mock_stuff_obj = Mock() 
     # When your real class is called, return value will be the mock_obj 
     self.my_class.return_value = self.mock_stuff_obj 

    def test_it(self): 
     do_something() 

     # assert your stuff here 
     self.my_class.assert_called_once_with(name='bob') 
     self.mock_stuff_obj.my_method.assert_called_once_with(num=10) 

    # stop the patcher in the tearDown 
    def tearDown(self): 
     self.patcher.stop() 

提供關於這是如何放在一起時,setUp方法,我們將提供功能能夠跨作爲文檔here解釋多種方法應用補丁裏面的一些見解。

的修補是在這兩條線進行:

# patch the class 
    self.patcher = patch('your_module.MyClass') 
    self.my_class = self.patcher.start() 

最後,在這裏創建的模擬對象:

# create your mock object 
    self.mock_stuff_obj = Mock() 
    self.my_class.return_value = self.mock_stuff_obj 

現在,所有的測試方法可以簡單地在所有使用self.my_classself.mock_stuff_obj你的電話。

+0

謝謝idjaw。我後來開始做一些這樣的事情,但這仍然非常有用,謝謝! –