如何在没有原始 PropertyMock 对象的情况下获取断言的 PropertyMock?
How to get PropertyMock for assertions without original PropertyMock object?
我为单元测试目的创建了一个 unittest.mock.PropertyMock
(docs) 对象,在对象中的一个属性上。
我不再引用 PropertyMock
,因为 PropertyMock
在测试设置期间被猴子修补了。
如果我拥有给定 property
的对象,我如何才能访问 PropertyMock
进行断言?
from typing import Any
from unittest.mock import PropertyMock
class Foo:
@property
def property_1(self) -> int:
return 1
def make_obj() -> Any:
"""Make some object, not returning a reference to the PropertyMock made inside."""
my_obj = Foo()
type(my_obj).property_1 = PropertyMock(return_value=100)
# NOTE: function doesn't return the PropertyMock, only the object
return my_obj
def test_make_obj() -> None:
made_obj = make_obj()
# We can see the PropertyMock is in place and works
assert made_obj.property_1 == 100
# How can I assert the property was set with 9001? NOTE: I don't have access
# to the PropertyMock made above
made_obj.property_1 = 9001
type(made_obj).property_1.assert_called_once_with(9001) # This fails
# AttributeError: 'int' object has no attribute 'assert_called_once_with'
换句话说:
- 在
PropertyMock
中进行猴子修补后
- 正在调用
type(my_obj).property_1
returns 100
- 我希望它 return
PropertyMock
使用(用于断言)
这有点棘手,因为通过属性访问 属性 模拟将始终 return 模拟的结果而不是模拟本身。
这是由于它的工作方式:PropertyMock
将 __get__
覆盖为 return 设置值,一旦您通过点符号使用属性访问(或者如果你使用 getattr
)。您不能自己覆盖 __get__
,因为那样会破坏 PropertyMock
.
的功能
您可以通过直接访问 class:
的 __dict__
来解决这个问题
def test_make_obj() -> None:
made_obj = make_obj()
assert made_obj.property_1 == 100
made_obj.property_1 = 9001
assert made_obj.property_1 == 9001
type(made_obj).__dict__["property_1"].assert_called_once_with(9001)
您可能可以使用一些辅助函数来使它更好一些,但是您仍然需要通过属性名称进行访问,至少我看不到其他方法。
我能想到的唯一其他可能性是通过 mock 本身,尽管这当然有些多余和丑陋:
def make_obj() -> Any:
my_obj = Foo()
pmock = PropertyMock(return_value=100)
type(my_obj).property_1 = pmock
return my_obj, pmock
def test_make_obj() -> None:
made_obj, pmock = make_obj()
assert made_obj.property_1 == 100
made_obj.property_1 = 9001
assert made_obj.property_1 == 9001
pmock.assert_called_once_with(9001)
我为单元测试目的创建了一个 unittest.mock.PropertyMock
(docs) 对象,在对象中的一个属性上。
我不再引用 PropertyMock
,因为 PropertyMock
在测试设置期间被猴子修补了。
如果我拥有给定 property
的对象,我如何才能访问 PropertyMock
进行断言?
from typing import Any
from unittest.mock import PropertyMock
class Foo:
@property
def property_1(self) -> int:
return 1
def make_obj() -> Any:
"""Make some object, not returning a reference to the PropertyMock made inside."""
my_obj = Foo()
type(my_obj).property_1 = PropertyMock(return_value=100)
# NOTE: function doesn't return the PropertyMock, only the object
return my_obj
def test_make_obj() -> None:
made_obj = make_obj()
# We can see the PropertyMock is in place and works
assert made_obj.property_1 == 100
# How can I assert the property was set with 9001? NOTE: I don't have access
# to the PropertyMock made above
made_obj.property_1 = 9001
type(made_obj).property_1.assert_called_once_with(9001) # This fails
# AttributeError: 'int' object has no attribute 'assert_called_once_with'
换句话说:
- 在
PropertyMock
中进行猴子修补后
- 正在调用
type(my_obj).property_1
returns100
- 我希望它 return
PropertyMock
使用(用于断言)
这有点棘手,因为通过属性访问 属性 模拟将始终 return 模拟的结果而不是模拟本身。
这是由于它的工作方式:PropertyMock
将 __get__
覆盖为 return 设置值,一旦您通过点符号使用属性访问(或者如果你使用 getattr
)。您不能自己覆盖 __get__
,因为那样会破坏 PropertyMock
.
您可以通过直接访问 class:
的__dict__
来解决这个问题
def test_make_obj() -> None:
made_obj = make_obj()
assert made_obj.property_1 == 100
made_obj.property_1 = 9001
assert made_obj.property_1 == 9001
type(made_obj).__dict__["property_1"].assert_called_once_with(9001)
您可能可以使用一些辅助函数来使它更好一些,但是您仍然需要通过属性名称进行访问,至少我看不到其他方法。
我能想到的唯一其他可能性是通过 mock 本身,尽管这当然有些多余和丑陋:
def make_obj() -> Any:
my_obj = Foo()
pmock = PropertyMock(return_value=100)
type(my_obj).property_1 = pmock
return my_obj, pmock
def test_make_obj() -> None:
made_obj, pmock = make_obj()
assert made_obj.property_1 == 100
made_obj.property_1 = 9001
assert made_obj.property_1 == 9001
pmock.assert_called_once_with(9001)