[英]Assert a function/method was not called using Mock
I'm using the Mock library to test my application, but I want to assert that some function was not called.我正在使用 Mock 库来测试我的应用程序,但我想断言某些函数没有被调用。 Mock docs talk about methods like
mock.assert_called_with
and mock.assert_called_once_with
, but I didn't find anything like mock.assert_not_called
or something related to verify mock was NOT called .模拟文档讨论了诸如
mock.assert_called_with
和mock.assert_called_once_with
类的方法,但我没有找到类似mock.assert_not_called
或与 verify mock mock.assert_not_called
NOT called相关的东西。
I could go with something like the following, though it doesn't seem cool nor pythonic:我可以使用以下内容,尽管它看起来既不酷也不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
Any ideas how to accomplish this?任何想法如何实现这一点?
This should work for your case;这应该适用于您的情况;
assert not my_var.called, 'method should not have been called'
Sample;样本;
>>> 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
Though an old question, I would like to add that currently mock
library (backport of unittest.mock) supports assert_not_called
method.虽然是一个老问题,但我想补充一下当前
mock
库(unittest.mock 的assert_not_called
移植)支持assert_not_called
方法。
Just upgrade yours;只需升级您的;
pip install mock --upgrade
You can check the called
attribute, but if your assertion fails, the next thing you'll want to know is something about the unexpected call, so you may as well arrange for that information to be displayed from the start.您可以检查被
called
属性,但是如果您的断言失败,那么您接下来想知道的是有关意外调用的信息,因此您最好从一开始就安排显示该信息。 Using unittest
, you can check the contents of call_args_list
instead:使用
unittest
,您可以检查call_args_list
的内容:
self.assertItemsEqual(my_var.call_args_list, [])
When it fails, it gives a message like this:当它失败时,它会给出如下消息:
AssertionError: Element counts were not equal: First has 0, Second has 1: call('first argument', 4)
使用python >= 3.5
您可以使用mock_object.assert_not_called()
。
When you test using class inherits unittest.TestCase you can simply use methods like:当您使用类继承unittest.TestCase 进行测试时,您可以简单地使用以下方法:
and similar (in python documentation you find the rest).和类似的(在python 文档中你可以找到其余的)。
In your example we can simply assert if mock_method.called property is False , which means that method was not called.在您的示例中,我们可以简单地断言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))
Judging from other answers, no one except @rob-kennedy talked about the call_args_list
.从其他答案来看,除了@rob-kennedy没有人谈到
call_args_list
。
It's a powerful tool for that you can implement the exact contrary of MagicMock.assert_called_with()
这是一个强大的工具,您可以实现与
MagicMock.assert_called_with()
完全相反的MagicMock.assert_called_with()
call_args_list
is a list of call
objects. call_args_list
是call
对象的列表。 Each call
object represents a call made on a mocked callable.每个
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)]
Consuming a call
object is easy, since you can compare it with a tuple of length 2 where the first component is a tuple containing all the positional arguments of the related call, while the second component is a dictionary of the keyword arguments.使用
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
So, a way to address the specific problem of the OP is因此,解决 OP 特定问题的一种方法是
def test_something():
with patch('something') as my_var:
assert ((some, args),) not in my_var.call_args_list
Note that this way, instead of just checking if a mocked callable has been called, via MagicMock.called
, you can now check if it has been called with a specific set of arguments.请注意,通过这种方式,您现在可以检查是否已使用一组特定的参数调用它,而不仅仅是检查是否已调用
MagicMock.called
可调用对象。
That's useful.这很有用。 Say you want to test a function that takes a list and call another function,
compute()
, for each of the value of the list only if they satisfy a specific condition.假设您要测试一个函数,该函数接受一个列表并仅在满足特定条件时才为列表的每个值调用另一个函数
compute()
。
You can now mock compute
, and test if it has been called on some value but not on others.您现在可以模拟
compute
,并测试它是否已被某些值而不是其他值调用。
根据 python stdlib 文档,对于python >= 3.5 应该使用 assert_not_call :
my_var.assert_not_called()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.