【问题标题】:unittest.Mock - Combining return_value and side_effectunittest.Mock - 结合 return_value 和 side_effect
【发布时间】:2017-11-08 10:05:13
【问题描述】:

是否可以让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 并不真正支持多语句 lambda(AFAIK,你能做的最好的就是将表达式放在一个元组中,但随后会返回整个元组) - 是否可以组合这两个参数?

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

【问题讨论】:

    标签: python unit-testing mocking


    【解决方案1】:

    “是否有可能让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 结合起来似乎是不可能的。

    【讨论】:

      【解决方案2】:

      需要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) 祝你好运:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-21
        • 1970-01-01
        • 2019-09-12
        • 1970-01-01
        • 1970-01-01
        • 2016-07-05
        • 2023-03-23
        • 1970-01-01
        相关资源
        最近更新 更多