2010-03-25 1 views
5

Ho una classe:Come faccio a prendere in giro una proprietà di classe con mox?

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

Utilizzando mox e py.test, come faccio a mock myproperty?

ho provato:

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

e

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

ma entrambi falliscono con AttributeError: can't set attribute.

+1

Utilizzare le maiuscole per le classi. –

risposta

9

Quando spegnendo gli attributi di classe mox utilizza setattr. Così

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

è equivalente a

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

Nota che a causa myproperty è una struttura getattr e setattr saranno invocano __get__ e __set__ metodi della proprietà, piuttosto che in realtà "beffardo fuori" la struttura in sé.

Così, per ottenere il risultato desiderato, basta fare un passo più in profondità e prendere in giro la proprietà nella classe dell'istanza.

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

Si noti che questo potrebbe causare problemi se si desidera contemporaneamente finte più istanze di MyClass con diversi myproperty valori.

3

Hai letto circa property? È di sola lettura, un "getter".

Se si desidera un setter, si ha due possibilità su come crearlo.

Una volta che hai sia getter che setter, puoi provare di nuovo a deriderli entrambi.

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

O

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

Sì, speravo di cavartela senza modificare la classe originale, anche se potrebbe non essere possibile. –

+2

Non puoi prendere in giro qualcosa che non esiste. La classe originale non può avere la proprietà impostata. Non puoi prendere in giro quella caratteristica perché non esiste. –