属性的魔术模拟设置值仅获取第一个值
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"
还可以,因为它更简洁一些,但是实际上忽略了键。
您可以按顺序使用 PropertyMock
和 side_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__
模拟中完成,而不是 属性 模拟。
一些参考资料:
我正在使用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"
还可以,因为它更简洁一些,但是实际上忽略了键。
您可以按顺序使用 PropertyMock
和 side_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__
模拟中完成,而不是 属性 模拟。
一些参考资料: