Python 断言未使用模拟调用函数/方法

Python 断言未使用模拟调用函数/方法,python,unit-testing,mocking,python-mock,Python,Unit Testing,Mocking,Python Mock,我正在使用模拟库来测试我的应用程序,但我想声明没有调用某些函数。Mock文档讨论的方法有Mock.assert\u调用和Mock.assert\u调用一次,但我没有发现类似Mock.assert\u未调用或与验证Mock是否未调用相关的内容 我可以选择下面这样的东西,尽管它看起来既不酷也不像蟒蛇: def test_something: # some actions with patch('something') as my_var: try:

我正在使用模拟库来测试我的应用程序,但我想声明没有调用某些函数。Mock文档讨论的方法有
Mock.assert\u调用
Mock.assert\u调用
一次,但我没有发现类似
Mock.assert\u未调用
或与验证Mock是否未调用相关的内容

我可以选择下面这样的东西,尽管它看起来既不酷也不像蟒蛇:

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=mock()
>>>mock.a()
>>>assert not mock.b.called,'b已被调用且不应被调用'
>>>assert not mock.a.called,'a已被调用且不应被调用'
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AssertionError:a已调用,不应该被调用

您可以检查
called
属性,但如果您的断言失败,接下来您需要了解的是有关意外调用的信息,因此您最好从一开始就安排显示该信息。使用
unittest
,您可以检查
call\u args\u list
的内容:

self.assertItemsEqual(my_var.call_args_list, [])
当它失败时,会发出如下信息:

AssertionError: Element counts were not equal: First has 0, Second has 1: call('first argument', 4) AssertionError:元素计数不相等: 第一个有0,第二个有1:call('First argument',4)
当您使用类继承的unittest.TestCase进行测试时,您可以简单地使用如下方法:

  • 资产真实
  • 资产虚假
  • 资产质量
和类似的(在你找到其余的)

在您的示例中,我们可以简单地断言ifmock_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))

从其他答案来看,除了
调用参数列表
,没有人谈论过

这是一个功能强大的工具,您可以实现与
MagicMock.assert\u完全相反的功能,并使用()调用\u

call\u args\u list
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)]
因此,解决OP具体问题的方法是

def test_something():
    with patch('something') as my_var:
        assert ((some, args),) not in my_var.call_args_list
注意,通过这种方式,您现在可以检查是否使用一组特定的参数调用了模拟可调用对象,而不是通过
MagicMock.called

>>> ((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
那很有用。假设您想测试一个函数,该函数接受一个列表,并且仅当列表中的每个值满足特定条件时,才调用另一个函数,
compute()


您现在可以模拟
compute
,并测试它是否在某些值上被调用,而不是在其他值上被调用。

虽然是一个老问题,但我想补充一点,当前
mock
库(unittest.mock的backport)支持
assert\u not\u called
方法

只要升级你的


pip安装mock——使用
python>=3.5升级
,您可以使用
mock\u对象。assert\u not\u called()
这个答案需要Django吗?我得到一个错误:
AttributeError:MockCallable实例没有属性“called”
@NathanArthur Hm,我不这么认为,在MacOS上的
sudo easy\U install-U mock
mock import mock
之后,上面的运行没有问题。从未安装过Django:)嗯,真奇怪。我正在运行Python2.7.1,并使用unittest和来自模拟导入模拟的
以及PythonMock 0.1.0进行测试。这听起来有问题吗?我正在模拟另一个模块中的可调用类,因此它看起来像是
模块\u to\u test.other\u module.class=mock.mock()?我认为在这种情况下调用计数不会重置,正如@Ahmet在他的回答中指出的,assert_not_called现在也得到了支持,在backport()中也是如此。