断言一个函数/方法不是使用Mock调用的

我正在使用模拟库来testing我的应用程序,但我想断言一些函数没有被调用。 模拟文档讨论像mock.assert_called_withmock.assert_called_once_with这样的方法,但是我没有发现任何类似mock.assert_not_called或者相关的东西来validationmock 没有被调用

我可以像下面这样做,虽然看起来不酷,也不像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 

你可以检查被called属性,但是如果你的断言失败了,接下来你想知道的是关于意外调用的东西,所以你可以安排从一开始就显示这些信息。 使用unittest ,你可以检查call_args_list的内容:

 self.assertItemsEqual(my_var.call_args_list, []) 

当它失败时,它会给出这样的信息:

 AssertionError:元素数不相等:
第一个有0,第二个有1:call('first argument',4)

虽然老问题,我想补充一点,目前mock库( assert_not_called backport)支持assert_not_called方法。

只是升级你的;

pip install mock --upgrade

当你使用类inheritanceunittest.TestCasetesting时,你可以简单地使用如下的方法:

  • assertTrue
  • assertFalse
  • assertEqual便

和类似的(在python文档中你可以find其他的)。

在你的例子中,我们可以简单地断言,如果mock_method.called属性是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()的完全相反

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检查是否调用了一个MagicMock.called可调用MagicMock.called ,现在可以检查是否使用了一组特定的参数调用它。

这很有用。 假设你想要testing一个带有列表的函数,并且只有满足一个特定的条件才能调用另一个函数compute()

你现在可以模拟compute ,并testing它是否被调用了一些值,而不是其他值。