【发布时间】:2018-12-06 09:09:20
【问题描述】:
是否可以在继续使用生产版本的其他同名字段/函数的同时模拟 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
换句话说,我只想模拟子类,而不是子类。我尝试过代替上面的嘲笑线的东西(两者都不起作用):
MyClass.SubClass.__init__ = Mock(side_effect=FakeSubClass.__init__)
MyClass.SubClass.__new__ = Mock(side_effect=FakeSubClass.__new__)
请注意,我知道可以通过多种方式重构代码以避免此问题,但遗憾的是无法重构代码。
【问题讨论】:
-
那些不是子类,不是面向对象编程语言上下文中术语的正常含义;您所拥有的只是属于其他类的属性的类。您通常希望避免这种情况。为什么要在这里嵌套类?
-
接下来,在创建单元测试时,您通常不会只模拟
__init__。你会模拟所有不是被测单元的东西。如果您认为要模拟该单元的__init__方法的类,请模拟__init__方法调用的内容,而不是方法本身。
标签: python unit-testing mocking python-mock