如何用mox模拟类属性?

5 投票
2 回答
6120 浏览
提问于 2025-04-15 20:50

我有一个类:

class MyClass(object):
    @property
    def myproperty(self):
        return 'hello'

使用 moxpy.test,我该如何模拟 myproperty 呢?

我试过:

mock.StubOutWithMock(myclass, 'myproperty')
myclass.myproperty = 'goodbye'

还有

mock.StubOutWithMock(myclass, 'myproperty')
myclass.myproperty.AndReturns('goodbye')

但是这两种方法都失败了,出现了 AttributeError: can't set attribute 的错误。

2 个回答

3

你有没有听说过property?它是只读的,叫做“获取器”。

如果你想要一个“设置器”,你有两种方法可以创建它。

当你同时拥有获取器和设置器后,就可以再试着模拟它们两个。

class MyClass(object): # Upper Case Names for Classes.
    @property
    def myproperty(self):
        return 'hello'
    @myproperty.setter
    def myproperty(self,value):
        self.someValue= value

或者

class MyClass(object): # Upper Case Names for Classes.
    def getProperty(self):
        return 'hello'
    def setProperty(self,value):
        self.someValue= value
    myproperty= property( getProperty, setProperty )
9

在创建类属性的占位符时,mox使用了setattr。所以

mock.StubOutWithMock(myinstance, 'myproperty')
myinstance.myproperty = 'goodbye'

其实是等同于

# Save old attribute so it can be replaced during teardown
saved = getattr(myinstance, 'myproperty')
# Replace the existing attribute with a mock
mocked = MockAnything()
setattr(myinstance, 'myproperty', mocked)

需要注意的是,因为myproperty是一个属性,getattrsetattr会调用这个属性的__get____set__方法,而不是直接“模拟”这个属性本身。

所以,要得到你想要的结果,你只需更进一步,直接在实例的类上模拟这个属性。

mock.StubOutWithMock(myinstance.__class__, 'myproperty')
myinstance.myproperty = 'goodbye'

请注意,如果你想同时模拟多个MyClass的实例,并且这些实例的myproperty值不同,这可能会引发一些问题。

撰写回答