Python mock return of a getattr() call

时间:2016-04-21 22:22:18

标签: python unit-testing mocking

Edit: I might be falling the XY problem trap here. Here's what I really want to know.

I have the following function:

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

In my test, I try to do:

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

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

Now what I want to do is to provide the expected_return_val onto the some_attr attribute on the bar object.

I have tried using PropertyMock:

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

Running my test I get the error:

TypeError: 'list' object is not callable

If the return_value is set to a scalar (not a list), the result of the getattr call in the real function is a mock, and not the scalar I provided.

Also, I'm worried about mocking out the getattr method, since it is a common method that will probably be used elsewhere in my function. How can I set a list on an attribute of my mock object under test?

1 个答案:

答案 0 :(得分: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 属性。用于引发异常或动态更改返回值。该函数使用与模拟相同的参数调用,除非它返回 DEFAULT,否则将使用该函数的返回值作为返回值。