[英]Assert a function/method was not called using Mock
我正在使用 Mock 庫來測試我的應用程序,但我想斷言某些函數沒有被調用。 模擬文檔討論了諸如mock.assert_called_with
和mock.assert_called_once_with
類的方法,但我沒有找到類似mock.assert_not_called
或與 verify mock mock.assert_not_called
NOT called相關的東西。
我可以使用以下內容,盡管它看起來既不酷也不pythonic:
def test_something:
# some actions
with patch('something') as my_var:
try:
# args are not important. func should never be called in this test
my_var.assert_called_with(some, args)
except AssertionError:
pass # this error being raised means it's ok
# other stuff
任何想法如何實現這一點?
這應該適用於您的情況;
assert not my_var.called, 'method should not have been called'
樣本;
>>> mock=Mock()
>>> mock.a()
<Mock name='mock.a()' id='4349129872'>
>>> assert not mock.b.called, 'b was called and should not have been'
>>> assert not mock.a.called, 'a was called and should not have been'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: a was called and should not have been
雖然是一個老問題,但我想補充一下當前mock
庫(unittest.mock 的assert_not_called
移植)支持assert_not_called
方法。
只需升級您的;
pip install mock --upgrade
您可以檢查被called
屬性,但是如果您的斷言失敗,那么您接下來想知道的是有關意外調用的信息,因此您最好從一開始就安排顯示該信息。 使用unittest
,您可以檢查call_args_list
的內容:
self.assertItemsEqual(my_var.call_args_list, [])
當它失敗時,它會給出如下消息:
AssertionError: Element counts were not equal: First has 0, Second has 1: call('first argument', 4)
使用python >= 3.5
您可以使用mock_object.assert_not_called()
。
當您使用類繼承unittest.TestCase 進行測試時,您可以簡單地使用以下方法:
和類似的(在python 文檔中你可以找到其余的)。
在您的示例中,我們可以簡單地斷言mock_method.call屬性是否為False ,這意味着未調用該方法。
import unittest
from unittest import mock
import my_module
class A(unittest.TestCase):
def setUp(self):
self.message = "Method should not be called. Called {times} times!"
@mock.patch("my_module.method_to_mock")
def test(self, mock_method):
my_module.method_to_mock()
self.assertFalse(mock_method.called,
self.message.format(times=mock_method.call_count))
從其他答案來看,除了@rob-kennedy沒有人談到call_args_list
。
這是一個強大的工具,您可以實現與MagicMock.assert_called_with()
完全相反的MagicMock.assert_called_with()
call_args_list
是call
對象的列表。 每個call
對象代表對模擬的可call
對象進行的調用。
>>> from unittest.mock import MagicMock
>>> m = MagicMock()
>>> m.call_args_list
[]
>>> m(42)
<MagicMock name='mock()' id='139675158423872'>
>>> m.call_args_list
[call(42)]
>>> m(42, 30)
<MagicMock name='mock()' id='139675158423872'>
>>> m.call_args_list
[call(42), call(42, 30)]
使用call
對象很容易,因為您可以將它與長度為 2 的元組進行比較,其中第一個組件是包含相關調用的所有位置參數的元組,而第二個組件是關鍵字參數的字典。
>>> ((42,),) in m.call_args_list
True
>>> m(42, foo='bar')
<MagicMock name='mock()' id='139675158423872'>
>>> ((42,), {'foo': 'bar'}) in m.call_args_list
True
>>> m(foo='bar')
<MagicMock name='mock()' id='139675158423872'>
>>> ((), {'foo': 'bar'}) in m.call_args_list
True
因此,解決 OP 特定問題的一種方法是
def test_something():
with patch('something') as my_var:
assert ((some, args),) not in my_var.call_args_list
請注意,通過這種方式,您現在可以檢查是否已使用一組特定的參數調用它,而不僅僅是檢查是否已調用MagicMock.called
可調用對象。
這很有用。 假設您要測試一個函數,該函數接受一個列表並僅在滿足特定條件時才為列表的每個值調用另一個函數compute()
。
您現在可以模擬compute
,並測試它是否已被某些值而不是其他值調用。
根據 python stdlib 文檔,對於python >= 3.5 應該使用 assert_not_call :
my_var.assert_not_called()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.