【问题标题】:How to test if instance's method is called with "self" when mocking?模拟时如何测试实例方法是否用“self”调用?
【发布时间】:2018-02-28 03:23:11
【问题描述】:

我正在使用unittest.mock,这个很棒的图书馆。但是,我对意外的行为感到惊讶,而且我没有看到明显的解决方案。我将它用于我的单元测试,并且完美地理解它是如何进行有用的测试是至关重要的。

我知道show_bar 中的以下代码已损坏,它调用的是类方法而不是实例方法。但是,我所有的 mock unittests 都通过了:

包含错误的代码

class Foo(object):
    def bar(self):
        return "bar"

    def show_bar(self):
        return Foo.bar()

预期用途:

foo = Foo()
assert foo.show_bar() == "bar"
# => throw exception: bar() missing 1 required positional argument: 'self'

Unittest 尝试使用 mock 捕获此错误但未成功:

from unittest.mock import patch
with patch.object(Foo, 'bar', return_value="bar") as mock:
    foo = Foo()
    assert foo.show_bar() == "bar"
mock.assert_called_once()
# => no errors 

理想情况下,我想断言 bar 被称为 self.bar() 而不是 Foo.bar() ;这是错误的。不幸的是,使用mock.assert_called_with() 没有考虑selfcls 参数,所以我有点困惑。

编辑:试图澄清。当我们需要修补对象的方法时,我正在寻找使用库unittest.mock 的最佳实践。我似乎不清楚如何修补它,目前我无法断言它是在调用 self.bar 还是 Foo.bar

【问题讨论】:

  • 不要模拟任何东西,只需在您的测试代码中调用f = Foo(); f.bar()。如果实现失败,它将引发TypeError,从而导致测试失败。
  • 还有 FWIW,这与 classmethod 无关 - 在您的示例中,Foo.bar 是一个未绑定的实例方法。
  • 抱歉,代码过于简单,我需要使用mock,因为方法的实际代码在不模拟其返回值的情况下是不可调用的。此外,当show_bar 开发人员调用Foo.bar() 时,我假设Foo.bar 是类方法或静态方法。这似乎是一个合理的说法?
  • 对不起,没有足够的上下文在这里做出明智的判断... wrt/类或静态方法部分我只是想明确指出Foo.bar 既不在您当前的实现中,而且看起来在课堂上也不会成为一个。可能在翻译中丢失了一些东西;)

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


【解决方案1】:

我真的不明白为什么你需要模拟该方法来测试它在调用时不会引发 TypeError 但无论如何......其他人可能会解释如何使用unittest.mock 解决这个问题,与此同时你可以自己跳过unittest.mock 并模拟Foo.bar

 callargs = dict()  
 def mock_bar(self):
     callargs["self"] = self
     return "bar"

 foobar = Foo.__dict__["bar"] 
 Foo.bar = mock_bar
 try: 
     foo = Foo()
     assert foo.show_bar() == "bar"
     assert "self" in callargs
     assert callargs["self"] is foo
 finally:
     Foo.bar = foobar

【讨论】:

  • 实际上我并没有试图解决我的问题,这是微不足道的,也没有“手动”模拟我的课程,我只是在寻找正确使用unittest.mock 来替换单元测试上下文中的方法调用。感谢您尝试提供帮助!
猜你喜欢
  • 2018-05-16
  • 2014-05-05
  • 1970-01-01
  • 2019-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
相关资源
最近更新 更多