【问题标题】:Python mock return of a getattr() callgetattr() 调用的 Python 模拟返回
【发布时间】:2016-04-21 22:22:18
【问题描述】:

编辑:我可能会陷入 XY 问题陷阱。这就是我真正想要的know

我有以下功能:

def foo():
  bar = funcToGetBar()
  return bar.getattr("some_attr", None)

在我的测试中,我尝试这样做:

mocked_bar = MagicMock()
expected_return_val = [obj1, obj2, ...]
funcToGetBar.return_value = mocked_bar  # funcToGetBar is patched

def testGetBar(self):
  assertEqual(expected_return_val, foo())

现在我要做的是将expected_return_val 提供给bar 对象的some_attr 属性。

我尝试过使用 PropertyMock:

type(mocked_bar).getattr = PropertyMock(return_value=expected_return_value)

运行我的测试我得到了错误:

TypeError: 'list' object is not callable

如果return_value 设置为标量(不是列表),则实际函数中getattr 调用的结果是模拟,而不是我提供的标量。

另外,我担心会模拟出getattr 方法,因为它是一种常见的方法,可能会在我的函数的其他地方使用。如何在被测模拟对象的属性上设置列表?

【问题讨论】:

  • 我没有关注所有内容,但我认为您想要getattr(bar, "some_attr", None),因为gettattr 是内置的全局函数,而不是所有内容都有的方法。
  • @AlexHall,使用该方法签名我最终得到了我的 MagicMock 对象,而不是我期望的列表。但这是朝着正确方向迈出的一步。

标签: python unit-testing mocking


【解决方案1】:

根据文档,Mock 的 return_value 不可迭代。要获得可迭代的 return_value,请使用 side_effect。

mocked_bar = MagicMock()
mocked_bar.side_effect = [obj1, obj2, ...]

编辑:文档位于https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock

具体来说:

side_effect:每当调用 Mock 时都会调用的函数。请参阅 side_effect 属性。对于引发异常或动态更改返回值很有用。该函数使用与 mock 相同的参数调用,除非它返回 DEFAULT,否则将使用此函数的返回值作为返回值。

【讨论】:

  • 能否添加文档链接?
  • @Danny_DD - 已添加。
  • 使用side_effect 表示[mocked_bar(), mocked_bar(), ...] == [obj1, obj2],而不是mocked_bar() == [obj1, obj2, ...]
  • 每次调用,你都会得到side_effect中的下一项。 --- 第一个 mocked_bar() == obj1 --- 第二个 mocked_bar() == obj2
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多