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

magic mock set value for attribute only get the first value

我正在使用pytest3.7进行测试。我想模拟 res,这是 get_res_function 的 return 值。 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”,有什么问题吗?

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

所以这个

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

喜欢这样做

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

还可以,因为它更简洁一些,但是实际上忽略了键。

您可以按顺序使用 PropertyMockside_effect 到 return 不同的东西:

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'

但是,请记住,无论输入键如何,它都会 return 相同的值。如果它用完 side_effects.

,它会提高 StopIteration

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

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

如果您愿意,您可以将函数作为 side_effect 传递,它将使用与模拟(密钥)相同的参数调用,然后您可以决定 return 取决于在钥匙上。但这需要在 __getitem__ 模拟中完成,而不是 属性 模拟。

一些参考资料: