0

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

4

1 回答 1

2

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

所以这

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

就像这样做

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

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

您可以使用PropertyMockwithside_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__模拟中完成,而不是在属性模拟中完成。

一些参考资料:

于 2019-12-11T17:59:35.553 回答