Python 2.7 模拟/补丁:理解 assert_called_XYZ()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20399327/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 20:20:23  来源:igfitidea点击:

Python 2.7 mock/patch: understanding assert_called_XYZ()

pythonunit-testingpython-2.7mocking

提问by try-catch-finally

I'm relatively new to Python and unit testing in Python. From the Java world I know the concept of mocking but it seem to be much different from what I can see in Python.

我对 Python 和 Python 中的单元测试比较陌生。从 Java 世界我知道模拟的概念,但它似乎与我在 Python 中看到的有很大不同。

I found this guide, which I found very helpful: http://www.voidspace.org.uk/python/mock/index.html

我找到了这个指南,我觉得它很有帮助:http: //www.voidspace.org.uk/python/mock/index.html

But as I wrote my (a bit more complex) tests with mocked out dependencies I noticed a strage behavior. I decided to create a reduced, simple example which also does not work as I expect it.

但是当我使用模拟依赖项编写我的(稍微复杂一点的)测试时,我注意到了一个奇怪的行为。我决定创建一个简化的、简单的示例,但它也无法按我的预期工作。

Take a look at this, the result and my expectation I have added as comments:

看看这个,结果和我作为评论添加的期望:

import unittest
from mock import patch, Mock, MagicMock

class BasicTest(unittest.TestCase):

    @patch("StringIO.StringIO")
    def testSomethingNotWorkingAsExpected(self, StringIOMock):
        StringIOMock.assert_called_once() # asserts, but why?

    @patch("StringIO.StringIO")
    def testSomethingSomehowWorking(self, StringIOMock):
        # self.instantiateStringIO() # intentionally commented out
        assert StringIOMock.called # does not assert (leading to failure of this test); as expected. If the above line is not commented, this asserts as expected.

    def instantiateStringIO(self):
        import StringIO
        StringIO.StringIO()

Why is assert_called_once()asserting the instantiation of StringIOeven it has not been instantiated yet? And why does assert ClassMock.calledbring the expected results?

为什么assert_called_once()断言它的实例化StringIO甚至还没有被实例化?而为什么会assert ClassMock.called带来预期的结果?

Using assert not ...to assert a method has not been called I found here: Assert a function/method was not called using Mock. I inverted this pattern in my case by omitting the not.

Using assert not ...to assert a method has not been called I found here: Assert a function/method was not called using Mock。在我的案例中,我通过省略not.

Somewhere I found the pattern ClassMock.return_valueto reference an instance. But I understand this as a way to manupulate the instance of a Mock before it will be called, not as a way to access the instance that might an underliing code have internally created. Or am I wrong?

在某处我找到了ClassMock.return_value引用实例的模式。但我理解这是一种在调用 Mock 实例之前对其进行操作的方法,而不是一种访问可能由底层代码在内部创建的实例的方法。还是我错了?

My environment:

我的环境:

  • Python 2.7.3
  • mock 0.8.8
  • Fedora 19
  • 蟒蛇 2.7.3
  • 模拟 0.8.8
  • 软呢帽 19

Probably my understanding of the mock/patch thing is wrong. Could please someone aditionally explain what a class mock does and how it works?

可能我对模拟/补丁的理解是错误的。可以请别人解释一下类模拟的作用以及它是如何工作的吗?

Edit1: Added output

编辑 1:添加输出

... and added paraphrase in parens to comment in testSomethingSomehowWorking

...并在括号中添加释义以评论 testSomethingSomehowWorking

This is the output:

这是输出:

.F
======================================================================
FAIL: testSomethingSomehowWorking (test_test.BasicTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/mock.py", line 1224, in patched
    return func(*args, **keywargs)
  File "test_test.py", line 15, in testSomethingSomehowWorking
    assert StringIOMock.called # does not assert; as expected
AssertionError

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (failures=1)

采纳答案by Simeon Visser

The method assert_called_oncedoes not exist and it does not perform an assertion. It's no different from writing StringIOMock.assert_foo_bar_does_not_exist()or any other method. The mock library doesn't check whether the method called on the mock actually exists.

该方法assert_called_once不存在且不执行断言。这与写作StringIOMock.assert_foo_bar_does_not_exist()或任何其他方法没有什么不同。模拟库不会检查在模拟上调用的方法是否实际存在。

If you use assert_called_once_withthen it fails as expected.

如果您使用,assert_called_once_with那么它会按预期失败。

You can use the specparameter to raise an error when you call a non-existent method:

spec当您调用不存在的方法时,您可以使用该参数引发错误:

@patch("StringIO.StringIO", spec=StringIO.StringIO)
def testSomethingNotWorkingAsExpected(self, StringIOMock):
    StringIOMock.assert_called_once() # will fail as the method doesn't exist