是否可以在继续使用生产版本时模拟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模拟的一个自动创建的属性。
我想要的输出如下:
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__)请注意,我知道有几种方法可以重构代码以避免这个问题,但遗憾的是,代码不能被重构。
发布于 2018-07-05 10:10:56
你也可以伪造这个类,在你的情况下,MyClass.SubClass.SubSubClass()做不到的事情是,MyClass.SubClass是一个模拟,没有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()发布于 2018-07-09 14:03:29
我同意ZhouQuan有一个非常好的答案,因为它适用于MyClass.Subclass上的任何方法或变量。尽管如此,这里有一些变化可能有用,也可能没有用。
如果由于任何原因不能直接编辑FakeSubClass,或者您只想继承SubSubClass(),而不想继承其他任何东西,那么可以在test()中这样修改它。
def test():
MyClass.SubClass()
MyClass.SubClass.SubSubClass()
FakeSubClass.SubSubClass = MyClass.SubClass.SubSubClass()
MyClass.SubClass = Mock(side_effect=FakeSubClass)
MyClass.SubClass()
MyClass.SubClass.SubSubClass()我认为值得注意的是,Mock确实接受了一个wraps参数,这个参数可以用于获得类似的行为,尽管这并不完全是您所要求的。下面是一个例子。
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:
def __init__(self) -> None:
print("\nfake init called")
def test():
MyClass.SubClass()
MyClass.SubClass.SubSubClass()
MyClass.SubClass = Mock(side_effect=FakeSubClass, wraps=MyClass.SubClass)
MyClass.SubClass()
MyClass.SubClass.SubSubClass()这提供了一个不同的输出。
real sub init called
real sub sub init called
fake init called # A call to MyClass.SubClass() causes both real and fake inits.
real sub init called # Same MyClass.SubClass() call.
real sub sub init called # But now the SubSubClass() does resolve correctly.https://stackoverflow.com/questions/51063324
复制相似问题