unittest.Mock - 结合return_value和side_effect

时间:2017-11-08 10:05:14

标签: python unit-testing mocking

调用时是否可以让Mock对象返回一个值,并在调用时执行一个语句?例如:

> mocked_func = Mock(return_value='Returned foo', 
                     side_effect=lambda: print('Side effect executed')
                    )

> print(mocked_func())

Side effect executed
None

这里的文档看起来有点模棱两可,但在我看来,当使用side_effect时,return_value被完全忽略,只返回side_effect函数的结果(在print()的案例为None)。

由于Python并不真正支持多语句lambdas(AFAIK,你可以做的最好的事情就是将表达式放在元组中,然后将返回整个元组) - 是否可以组合这两个参数?

我想避免必须定义一个新函数并将其用作side_effect,我觉得在Mock中声明的更清晰。

2 个答案:

答案 0 :(得分:3)

答案是"是否可以让一个Mock对象在被调用时返回一个值,并在被调用时执行一个语句?"显然是的,只需让side_effect做所有事情:

import unittest.mock as mock

def side_effect():
      print('Side effect executed')
      return 'Returned Foo'

mocked_func = mock.Mock(side_effect=side_effect)

print(mocked_func())

# output
Side effect executed
Returned Foo

当然你也可以用lambda做到这一点:

import unittest.mock as mock

mocked_func = mock.Mock(
    side_effect=lambda: (print('Side effect executed'), 'Returned Foo')[1]
)

print(mocked_func())

# output
Side effect executed
Returned Foo

对我而言,它看起来并不干净,但对每个人来说都是如此。如果您只是想避免污染命名空间,可以执行以下操作:

def mocked_func():
    print('Side effect executed')
    return 'Returned Foo'
mocked_func = mock.Mock(side_effect=mocked_func)

或使用装饰者:

def mock_it(f):
    return mock.Mock(side_effect=f)

@mock_it
def mocked_func():
    print('Side effect executed')
    return 'Returned Foo'

正如您已经注意到的那样,似乎无法合并return_valueside_effect

答案 1 :(得分:0)

需要python版本> = 3.3

0)import unittest.mock.DEFAULT

1)使side_effect函数返回DEFAULT

def func():
    print('I am func(), and side_effect() called me!!')
    return  DEFAULT

4)创建模拟

 nice_print = 'I am a return value that side_effect() cannot override because 
               side_effect() returns special obj called DEFAULT'
 mocked_func = mock.Mock(side_effect=func, return_value=nice_print)

3)祝你好运:)