是否可以在继续使用生产版本的同名其他字段/函数的同时模拟 python 构造函数?例如,给定生产代码:
class MyClass:
class SubClass:
def __init__(self) -> None:
print("\nreal sub init called")
class SubSubClass:
def __init__(self) -> None:
print("\nreal sub sub init called")
和下面的测试代码:
class FakeSubClass:
def __init__(self) -> None:
print("\nfake init called")
def test():
MyClass.SubClass()
MyClass.SubClass.SubSubClass()
MyClass.SubClass = Mock(side_effect=FakeSubClass)
MyClass.SubClass()
MyClass.SubClass.SubSubClass()
我们得到以下输出:
real sub init called
real sub sub init called
fake init called
请注意,最后一行 MyClass.SubClass.SubSubClass()
并未创建真正的 SubSubClass,因为此时它是 SubClass mock 的自动创建属性。
我想要的输出如下:
real sub init called
real sub sub init called
fake init called
real sub sub init called
换句话说,我只想模拟 SubClass,而不是 SubSubClass。我已经尝试代替上面的模拟行的东西(两者都不起作用):
MyClass.SubClass.__init__ = Mock(side_effect=FakeSubClass.__init__)
MyClass.SubClass.__new__ = Mock(side_effect=FakeSubClass.__new__)
请注意,我知道有几种重构代码的方法可以避免此问题,但遗憾的是代码无法重构。
最佳答案
你也可以伪造类,MyClass.SubClass.SubSubClass()
在你的情况下不起作用是因为 MyClass.SubClass
是一个 Mock 没有 SubSubClass
定义。只需让 FakeSubClass
从 MyClass.SubClass 继承它即可解决问题。
并且您可以轻松地将 MyClass
修补为 FakeClass
,并且您将拥有正确的测试对象而不是真实对象。
from unittest.mock import Mock
class MyClass:
class SubClass:
def __init__(self) -> None:
print("\nreal sub init called")
class SubSubClass:
def __init__(self) -> None:
print("\nreal sub sub init called")
class FakeSubClass(MyClass.SubClass, Mock):
def __init__(self) -> None:
print("\nfake init called")
class FakeClass:
class SubClass(FakeSubClass):
pass
def test():
MyClass.SubClass()
MyClass.SubClass.SubSubClass()
MyClass.SubClass = Mock(side_effect=FakeSubClass)
FakeClass.SubClass()
FakeClass.SubClass.SubSubClass()
关于python - 可以在不模拟对象的其他属性的情况下模拟 python 构造函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51063324/