属性的魔术模拟设置值仅获得第一个值

时间:2019-12-11 17:16:46

标签: python mocking pytest magicmock

我正在使用pytest3.7进行测试。我想模拟res,它是get_res_function的返回值。 res.property1[key1][keyN].property2是我要模拟的值。这是我的测试:

@mock.patch("mypkg.get_res_function")
def test_function(mock_res):
    returner = mock.MagicMock()
    returner.property1["key1"]["key2"].property2 = "11111"
    returner.property1["key1"]["key3"].property2 = "22222"
    mock_res.return_value = returner

但是,我要模拟的两个值仅使用第一行模拟的值,这意味着mock_res.property1["key1"]["key2"].property2 = "11111", mock_res_property1["key1"]["key3"].property2 = "11111" 并且如果在测试代码中将其反转,则意味着将“ 22222”放在“ 11111”之前,

returner.property1["key1"]["key2"].property2 = "22222"
        returner.property1["key1"]["key3"].property2 = "11111"

那么所有结果都是“ 22222”,这是什么问题?

1 个答案:

答案 0 :(得分:1)

这很棘手,因为项目访问语法thing[index]实际上是在调用魔术方法__getitem__,而这正是您要模拟的内容。

所以这个

returner.property1["key1"]["key2"].property2 = "11111"

喜欢这样做

returner.property1.__getitem__.return_value.__getitem__.return_value.property2 = "11111"

没关系,因为它更加简洁,但是实际上忽略了键。

您可以将PropertyMockside_effect一起使用,以按顺序返回不同的内容:

type(returner.property1.__getitem__.return_value.__getitem__.return_value).property2 = PropertyMock(side_effect=["11111", "22222"])

或者,返回以获得项目语法:

type(returner.property1["this is"]["ignored"]).property2 = PropertyMock(side_effect=["11111", "22222"])

它应该可以工作:

returner.property1["foo"]["bar"].property2
> '11111'
returner.property1["foo"]["bar"].property2
> '22222'

但是,请记住,无论输入键如何,它将返回相同的值。如果用完StopIteration,它将提高side_effects

您可以断言哪些键实际用于调用__getitem__

returner.property1.__getitem__.call_args_list
returner.property1.__getitem__.return_value.__getitem__.call_args_list

如果愿意,可以改为使用side_effect作为函数,该函数将使用与模拟(键)相同的参数进行调用,然后可以根据键决定返回什么。但这需要在__getitem__模拟中完成,而不是在属性模拟中完成。

一些参考文献: