2016-03-10 13 views
14

Quando si applica una patch una funzione tramite finto, si ha la possibilità di specificare Autospec come True:Quando si utilizza unittest.mock.patch, perché autospec non è True per impostazione predefinita?

Se si imposta Autospec = True poi il mock con essere creati con una specifica dall'oggetto da sostituire. Tutti gli attributi della simulazione saranno anche hanno la specifica dell'attributo corrispondente dell'oggetto sostituito. I metodi e le funzioni che vengono derisi avranno i loro argomenti controllati e genereranno un TypeError se vengono chiamati con la firma errata.

(http://www.voidspace.org.uk/python/mock/patch.html)

mi chiedo perché questo non è il comportamento di default? Sicuramente vorremmo quasi sempre intercettare i parametri errati su qualsiasi funzione che applichiamo?

risposta

14

L'unico modo chiaro per spiegare questo, è quello di citare in realtà il documentation sul svantaggio di utilizzare auto-speccing e perché si dovrebbe fare attenzione quando lo si utilizza:

Questo non è senza avvertimenti e limitazioni, che è il motivo per cui è non il comportamento predefinito. Per sapere quali attributi sono disponibili su sull'oggetto spec, autospec deve analizzare (accedere agli attributi ) le specifiche. Mentre si attraversano gli attributi sulla simulazione, una traversata corrispondente dell'oggetto originale sta avvenendo sotto il cofano . Se uno qualsiasi degli oggetti specificati dispone di proprietà o descrittori che possono attivare l'esecuzione del codice, potrebbe non essere possibile utilizzare autospec. D'altra parte è molto meglio progettare gli oggetti in modo che l'introspezione sia sicura [4].

Un problema più serio è che è comune ad esempio attribuisce essere creato nella init metodo e non esiste sulla classe a tutto. autospec non può conoscere alcuno degli attributi creati dinamicamente e limita l'api agli attributi visibili.

penso che il takeaway chiave qui è da notare questa linea: Autospec non può sapere su eventuali attributi creati dinamicamente e limita l'API per attributi visibili

Quindi, a meno di essere più esplicito con una esempio di pause in cui autospeccing, questo esempio tratto dalla documentazione mostra questo:

>>> class Something: 
... def __init__(self): 
...  self.a = 33 
... 
>>> with patch('__main__.Something', autospec=True): 
... thing = Something() 
... thing.a 
... 
Traceback (most recent call last): 
    ... 
AttributeError: Mock object has no attribute 'a' 

Come si può vedere, autospeccing non ha idea che ci sia un attributo a in fase di creazione durante la creazione del Something oggetto.

In genere, per me stesso, ho appena preso in giro la patch e non uso molto l'autospec, poiché il comportamento è in genere in linea con le mie aspettative.

Non c'è niente di sbagliato nell'assegnare un valore all'attributo di istanza.

Osservare l'esempio seguente funzionale:

import unittest 
from mock import patch 

def some_external_thing(): 
    pass 

def something(x): 
    return x 

class MyRealClass: 
    def __init__(self): 
     self.a = some_external_thing() 

    def test_thing(self): 
     return something(self.a) 



class MyTest(unittest.TestCase): 
    def setUp(self): 
     self.my_obj = MyRealClass() 

    @patch('__main__.some_external_thing')  
    @patch('__main__.something') 
    def test_my_things(self, mock_something, mock_some_external_thing): 
     mock_some_external_thing.return_value = "there be dragons" 
     self.my_obj.a = mock_some_external_thing.return_value 
     self.my_obj.test_thing() 

     mock_something.assert_called_once_with("there be dragons") 


if __name__ == '__main__': 
    unittest.main() 

Così, sto solo dicendo per il mio banco di prova che voglio fare in modo che il metodo some_external_thing() non influisce sul comportamento del mio unittest, quindi sono semplicemente assegnando il mio attributo di istanza al mockage per mock_some_external_thing.return_value = "there be dragons".

Problemi correlati