我对Python和Python中的单元测试比较陌生。从Java世界我知道模拟的概念,但它似乎与我在Python中看到的大不相同。
我找到了这个指南,我发现它非常有用:http://www.voidspace.org.uk/python/mock/index.html
但是当我使用模拟的依赖关系编写我的(更复杂的)测试时,我注意到了一种暴力行为。 我决定创建一个简化的简单示例,它也不像我预期的那样工作。
看看这个,结果以及我作为评论添加的期望:
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()
为什么assert_called_once()
断言StringIO
的实例化,即使它尚未实例化?
为什么assert ClassMock.called
会带来预期的结果?
使用assert not ...
断言方法尚未调用我在此处找到:Assert a function/method was not called using Mock。我省略了not
。
在某处我找到了引用实例的模式ClassMock.return_value
。但我理解这是一种在调用Mock之前对其进行管理的方法,而不是作为访问可能是内部创建的底层代码的实例的方法。还是我错了?
我的环境:
可能我对模拟/补丁的理解是错误的。可以请某人在某种程度上解释一下类模拟的作用以及它是如何工作的吗?
...并在parens中添加释义以在testSomethingSomehowWorking
这是输出:
.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)
答案 0 :(得分:12)
方法assert_called_once
不存在,并且不执行断言。它与编写StringIOMock.assert_foo_bar_does_not_exist()
或任何其他方法没有什么不同。模拟库不会检查模拟上调用的方法是否确实存在。
如果您使用assert_called_once_with
,则会按预期失败。
当您调用不存在的方法时,可以使用spec
参数引发错误:
@patch("StringIO.StringIO", spec=StringIO.StringIO)
def testSomethingNotWorkingAsExpected(self, StringIOMock):
StringIOMock.assert_called_once() # will fail as the method doesn't exist