12

我有一些代码调用集合中每个项目的一系列方法,每个方法返回一个布尔值,指示成功 = True/failure = False。

def monkey(some_collection, arg1, arg2):
    for item in some_collection:
        if not item.foo(arg1, arg2):
            continue
        if not item.bar(arg1, arg2):
            continue
        if not item.baz(arg1, arg2):
            continue

而且,这是我的单元测试示例:

import mock
def TestFoo(unittest.TestCase):
    def test_monkey(self):
        item = MagicMock()
        some_collection = [item]
        collection_calls = []
        foo_call = mock.call().foo(some_collection, 1, 2)
        bar_call = mock.call().bar(some_collection, 1, 2)
        baz_call = mock.call().baz(some_collection, 1, 2)
        collection_calls = [foo_call, bar_call, baz_call]                   
        my_module.monkey(some_collection, 1, 2)
        item.assert_has_calls(collection_calls) # requires the correct call order/sequence

实际通话

  1. call().foo(<MagicMock id='12345'>, 1, 2)
  2. call().foo.__nonzero__()

...

注意:此单元测试失败,因为它看到了__nonzero__()方法调用。

问题

为什么要添加非零方法调用?

澄清

我正在使用mock,它从 python 3.3 开始包含在 stdlib 中。

4

1 回答 1

21

简短的回答:

如果您的模拟函数没有返回的显式 return_value 或 side_effect,您将在 Python 尝试评估模拟的真实性时看到这一点。确保你的模拟有一个。

要么用一个初始化它:

item = MagicMock(return_value=True)

或添加一个:

item.return_value = True

解释:

当你这样做时if not x:,你可能正在思考if x is False

Python 实际上并没有这样做——它确实这样做了if bool(x) is False(这是 Python 的真实性概念——值评估为Trueor False),bool(x)实际上是对x.__nonzero__()(或x.__bool__()在 3.x 中)的调用。

这是为了提供 Python 的良好if行为 - 当您这样做时if []:,许多语言会将任何对象视为True,但 Python 旨在使代码可读,因此它委托并且列表的__nonzero__()方法将False在它为空时返回。这允许更多的代码读起来更自然,并解释了为什么你会看到这些调用。

于 2012-12-26T21:09:26.040 回答