如何用mox模拟类属性?
我有一个类:
class MyClass(object):
@property
def myproperty(self):
return 'hello'
使用 mox
和 py.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
是一个属性,getattr
和setattr
会调用这个属性的__get__
和__set__
方法,而不是直接“模拟”这个属性本身。
所以,要得到你想要的结果,你只需更进一步,直接在实例的类上模拟这个属性。
mock.StubOutWithMock(myinstance.__class__, 'myproperty')
myinstance.myproperty = 'goodbye'
请注意,如果你想同时模拟多个MyClass
的实例,并且这些实例的myproperty
值不同,这可能会引发一些问题。