Как смоделировать свойство класса с помощью 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.


person Harley Holcombe    schedule 25.03.2010    source источник
comment
Пожалуйста, используйте имена классов в верхнем регистре.   -  person S.Lott    schedule 25.03.2010


Ответы (2)


При заглушке атрибутов класса 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.

person brotchie    schedule 25.03.2010

Вы читали о свойстве? Это только для чтения, "геттер".

Если вам нужен сеттер, у вас есть два варианта его создания.

Когда у вас есть и геттер, и сеттер, вы можете снова попытаться смоделировать их обоих.

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

Or

class MyClass(object): # Upper Case Names for Classes.
    def getProperty(self):
        return 'hello'
    def setProperty(self,value):
        self.someValue= value
    myproperty= property( getProperty, setProperty )
person S.Lott    schedule 25.03.2010
comment
Да, я надеялся избежать наказания, не изменяя исходный класс, хотя, возможно, это невозможно. - person Harley Holcombe; 26.03.2010
comment
Нельзя издеваться над тем, чего нет. В исходном классе не могло быть установлено это свойство. Вы не можете издеваться над этой функцией, потому что она не существует. - person S.Lott; 26.03.2010