unittest.Mock - 结合 return_value 和 side_effect

Mar*_*lka 2 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
Run Code Online (Sandbox Code Playgroud)

这里的文档似乎有点含糊,但在我看来,side_effect使用 when 时,then被完全忽略,只返回 functionreturn_value的结果(在is的情况下)。side_effectprint()None

由于Python并不真正支持多语句lambda(据我所知,你能做的最好的事情就是将表达式放入一个元组中,但随后将返回整个元组) - 是否可以组合两个参数?

我想避免必须定义一个新函数并将其用作side_effect,我觉得在 a 中声明两者Mock更干净。

Sto*_*ica 6

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
Run Code Online (Sandbox Code Playgroud)

当然你也可以用 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
Run Code Online (Sandbox Code Playgroud)

对我来说,它看起来并不干净,但对每个人来说,它看起来并不干净。如果您只是想避免污染您的名称空间,您可以这样做:

def mocked_func():
    print('Side effect executed')
    return 'Returned Foo'
mocked_func = mock.Mock(side_effect=mocked_func)
Run Code Online (Sandbox Code Playgroud)

或者使用装饰器:

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

@mock_it
def mocked_func():
    print('Side effect executed')
    return 'Returned Foo'
Run Code Online (Sandbox Code Playgroud)

正如您已经注意到的那样,结合return_valueside_effect似乎是不可能的。