使用自定义mock类的Python unittest补丁

2024-04-20 08:31:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在测试一段相对简单的代码,它使用两个需要磁盘访问的相对复杂的对象。复杂的对象来自一个库。我想模拟这些库对象,并断言它们的一些成员函数是使用特定值调用的,这取决于输入。在

我使用的调用依赖于库对象的某些内部状态。我认识到我可以单独模拟复杂对象上的每个函数调用,并在每个调用之前设置一个return_value。不过,这似乎比它需要的混乱和痛苦得多。在

似乎您应该能够提供一个自定义类并用一个模拟对象包装它,以跟踪对成员函数的所有调用。我花了几个小时试图弄清楚official documentation,而我发现的最接近的是wraps参数。不幸的是,这似乎并没有用包装的模拟替换所有成员,而是使用模拟对象的成员变量,只跟踪对__init__的调用。在

例如,在模块中:

# Assuming some library class that acts something like this:
class A:
  def __init__(self, filename):
    self.filename = filename
  def get(self):
    # ... Some complicated code, involving state and disk access ...
    return something

def some_fnc(filename):
  a = A(filename)
  a.get()
  a.get()
  a.get()
  a.get()

测试模块中

^{pr2}$

在摩卡。快调用,第一个assert通过,但第二个assert失败。在

有没有我缺少的功能?有可能做我想做的事吗?我的建议有什么特别糟糕的原因吗?在


Tags: 模块对象函数代码selfgetreturninit
1条回答
网友
1楼 · 发布于 2024-04-20 08:31:08

当被调用方尝试实例化module_a.A时,可以使用patch的模拟对象返回MagicMock的实例,该实例包装了模拟类。在

class SomeFncTestCase(unittest.TestCase):
  @unittest.mock.patch('module_a.A')
  def test_it(self, m):
    mock_a = MagicMock(wraps=MockA())
    m.return_value = mock_a

    module_a.some_fnc('in_file')

    m.assert_called_with('in_file')
    mock_a.get.assert_called()

m实质上模拟A.__call__的Mock和mock_a之间有区别,后者是A类的模拟实例化(它通过包装MockA的实例来提供实际的函数返回值)。在

相关问题 更多 >