【问题标题】:python check if a method is called without mocking it awaypython检查一个方法是否被调用而不模拟它
【发布时间】:2018-11-30 21:11:15
【问题描述】:
class A():
    def tmp(self):
        print("hi")

def b(a):
    a.tmp()

要检查是否在b中调用了tmp方法,推荐的方法是

a = A()
a.tmp = MagicMock()
b(a)
a.tmp.assert_called()

但是这里的 tmp 被嘲笑了,并没有导致 "hi" 被打印出来。

我希望我的单元测试检查是否调用了方法 tmp 而不模拟它。

这可能吗?

我知道在编写单元时这不是一个标准的事情。但我的用例(有点棘手)需要这个。

【问题讨论】:

    标签: python python-3.x unit-testing mocking magicmock


    【解决方案1】:

    您可以将Mock.side_effect 设置为原始方法。

    from unittest.mock import MagicMock
    
    class A():
        def tmp(self):
            print("hi")
    
    def b(a):
        a.tmp()
    
    a = A()
    a.tmp = MagicMock(side_effect=a.tmp)
    b(a)
    a.tmp.assert_called()
    

    side_effect是一个函数(或者本例中的绑定方法,这是一种函数)时,调用Mock也会调用side_effect,参数相同。

    Mock() 调用将返回 side_effect 返回的任何内容,除非它返回 unnittest.mock.DEFAULT 单例。然后它将返回Mock.return_value

    【讨论】:

    • def tmp(self): return "hi"
    • 如果我也关心返回值怎么办?
    • @claudius 你试过了吗?调用 Mock 对象应该返回 side_effect 使用这些参数返回的任何内容。
    • 导入应该来自模拟导入 MagicMock :)
    【解决方案2】:

    或者你可以装饰方法来测试:

    def check_called(fun):
        def wrapper(self, *args, **kw):
            attrname = "_{}_called".format(fun.__name__)
            setattr(self, attrname, True)
            return fun(self, *args, **kw)
        return wrapper
    
    
    a = A()
    a.tmp = check_called(a.tmp)
    b(a)
    assert(getattr(a, "_tmp_called", False))
    

    但如果您已经在使用 Mock,MagicMock 的 side_effect 绝对是一个更好的解决方案;)

    【讨论】:

      猜你喜欢
      • 2014-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-12
      • 1970-01-01
      • 2017-12-15
      • 1970-01-01
      相关资源
      最近更新 更多