Как мне макетировать свойство класса с помощью mox? - PullRequest
5 голосов
/ 25 марта 2010

У меня есть класс:

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 ]

9 голосов
/ 26 марта 2010

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

3 голосов
/ 25 марта 2010

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

Если вы хотите установить, у вас есть два варианта, как его создать.

Если у вас есть и геттер, и сеттер, вы можете попробовать еще раз, чтобы сменить их обоих.

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 )
...