首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可以在不模拟对象的其他属性的情况下对python构造函数进行模拟吗?

可以在不模拟对象的其他属性的情况下对python构造函数进行模拟吗?
EN

Stack Overflow用户
提问于 2018-06-27 12:53:42
回答 2查看 4.7K关注 0票数 6

是否可以在继续使用生产版本时模拟python构造函数--其他字段/函数使用相同的名称?例如,给定生产代码:

代码语言:javascript
复制
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")

以及以下测试代码:

代码语言:javascript
复制
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()

我们得到以下输出:

代码语言:javascript
复制
real sub init called

real sub sub init called

fake init called

注意,最后一行MyClass.SubClass.SubSubClass()没有创建真正的SubSubClass,因为此时它是SubClass模拟的一个自动创建的属性。

我想要的输出如下:

代码语言:javascript
复制
real sub init called

real sub sub init called

fake init called

real sub sub init called

换句话说,我只想模拟SubClass,而不是SubSubClass。我试过的东西代替了上面的嘲弄线(这两种方法都行不通):

代码语言:javascript
复制
MyClass.SubClass.__init__ = Mock(side_effect=FakeSubClass.__init__)

MyClass.SubClass.__new__ = Mock(side_effect=FakeSubClass.__new__)

请注意,我知道有几种方法可以重构代码以避免这个问题,但遗憾的是,代码不能被重构。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-05 10:10:56

你也可以伪造这个类,在你的情况下,MyClass.SubClass.SubSubClass()做不到的事情是,MyClass.SubClass是一个模拟,没有SubSubClass定义。只要让FakeSubClass从MyClass.SubClass继承它就可以解决这个问题。

您可以轻松地将MyClass修补到FakeClass,并且您将拥有正确的测试对象而不是真实的对象。

代码语言:javascript
复制
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()
票数 4
EN

Stack Overflow用户

发布于 2018-07-09 14:03:29

我同意ZhouQuan有一个非常好的答案,因为它适用于MyClass.Subclass上的任何方法或变量。尽管如此,这里有一些变化可能有用,也可能没有用。

如果由于任何原因不能直接编辑FakeSubClass,或者您只想继承SubSubClass(),而不想继承其他任何东西,那么可以在test()中这样修改它。

代码语言:javascript
复制
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参数,这个参数可以用于获得类似的行为,尽管这并不完全是您所要求的。下面是一个例子。

代码语言:javascript
复制
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()

这提供了一个不同的输出。

代码语言:javascript
复制
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.
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51063324

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档