簡體   English   中英

在python單元測試中模擬一個類和一個類方法

[英]Mock a class and a class method in python unit tests

我正在使用python的unittest.mock在Django應用程序中進行一些測試。 我想檢查一個類是否被調用,並且還調用了它的實例上的方法。

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

# 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 我知道我錯過了一些東西 - 在模擬類上嘲笑一個方法? - 但我不確定是什么或如何使它工作。

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

像這樣調用模擬對象,

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

對您的單元測試的一個小的重構建議,以幫助您在測試中可能遇到的其他實例方法。 您可以在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方法,我們將提供功能能夠跨多個方法應用補丁作為文檔解釋這里

修補程序在以下兩行中完成:

    # 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

這條線

 my_class.my_method.assert_called_once_with(num=10)

如果my_method是一個類方法,它將起作用。

是這樣的嗎?

否則,如果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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM