Mock vs MagicMock


138

La mia comprensione è che MagicMock è un superset di Mock che esegue automaticamente "metodi magici" fornendo così in modo continuo supporto per elenchi, iterazioni e così via ... Allora qual è la ragione per cui esiste Mock ? Non è solo una versione ridotta di MagicMock che può essere praticamente ignorata? La classe Mock conosce qualche trucco che non è disponibile in MagicMock ?

Risposte:


99

Qual è la ragione per l' esistenza di Mock semplice ?

L'autore di Mock, Michael Foord, ha posto una domanda molto simile a Pycon 2011 (31:00) :

Q: Perché MagicMock è stato creato separatamente anziché semplicemente piegare l'abilità nell'oggetto di simulazione predefinito?

A: Una risposta ragionevole è che il modo in cui funziona MagicMock è che preconfigura tutti questi metodi di protocollo creando nuovi Mock e impostandoli, quindi se ogni nuovo mock ha creato un gruppo di nuovi mock e li imposta come metodi di protocollo e quindi tutti quei protocolli i metodi hanno creato un sacco di beffe e li hanno impostati sui loro metodi di protocollo, hai una ricorsione infinita ...

Cosa succede se si desidera che l'accesso al mock come oggetto contenitore sia un errore - non si desidera che funzioni? Se ogni finto ha automaticamente tutti i metodi di protocollo, allora diventa molto più difficile farlo. Inoltre, MagicMock fa un po 'di questa preconfigurazione per te, impostando valori di ritorno che potrebbero non essere appropriati, quindi ho pensato che sarebbe meglio avere questa convenienza che ha tutto preconfigurato e disponibile per te, ma puoi anche prendere una derisione ordinaria oggetto e configura solo i metodi magici che vuoi esistere ...

La semplice risposta è: usa MagicMock ovunque se questo è il comportamento che desideri.


12
Penso che una risposta migliore sia: usa MagicMock se sai cosa stai facendo, altrimenti usa Mock.
laike9m,

56

Con Mock puoi deridere metodi magici ma devi definirli. MagicMock ha "implementazioni predefinite della maggior parte dei metodi magici". .

Se non hai bisogno di testare alcun metodo magico, Mock è adeguato e non porta molte cose estranee nei tuoi test. Se devi testare molti metodi magici, MagicMock ti farà risparmiare un po 'di tempo.


Abbastanza sicuro ho già letto la documentazione. Questo non risponde alla mia domanda: perché preoccuparsi del semplice Mock se MagicMock fa esattamente lo stesso e molto altro? Nei miei test non vedo cose estranee: uso solo il nome diverso e basta. Quindi dov'è il trucco?
Vladimir Ignatov,

39
I test dovrebbero essere minimi e gli oggetti finti dovrebbero essere minimamente funzionali in modo da essere sicuri esattamente di cosa stai testando. Se usi MagicMock solo perché fa di più ma non stai testando esplicitamente tutto quel "di più" corri il rischio di fallire un test a causa di un comportamento predefinito di MagicMock. Questo fallimento potrebbe riflettere qualcosa sulle impostazioni predefinite di MagicMock più della cosa che dovrebbe deridere. Ancora peggio, si corre il rischio che un test abbia esito positivo quando avrebbe dovuto fallire. Il rischio è piccolo ma se ciò accade, ti farà perdere molto tempo.
Sean Redmond,

1
Ci penso come usare semplicemente JS vs Jquery. Certo, si potrebbe utilizzare jQuery per fare tutto il vostro JS, ma in alcuni casi, si vuole solo utilizzare lo strumento molto minima richiesta per ottenere il lavoro fatto. Trovo che quei casi di solito siano estremamente semplici o estremamente complessi.
coccole il

49

Per cominciare, MagicMockè una sottoclasse di Mock.

class MagicMock(MagicMixin, Mock)

Di conseguenza, MagicMock fornisce tutto ciò che Mock fornisce e altro ancora. Invece di pensare a Mock come una versione ridotta di MagicMock, pensa a MagicMock come una versione estesa di Mock. Questo dovrebbe rispondere alle tue domande sul perché Mock esiste e cosa offre Mock oltre a MagicMock.

In secondo luogo, MagicMock fornisce implementazioni predefinite di molti / molti metodi magici, mentre Mock no. Vedi qui per maggiori informazioni sui metodi magici forniti.

Alcuni esempi di metodi magici forniti:

>>> int(Mock())
TypeError: int() argument must be a string or a number, not 'Mock'
>>> int(MagicMock())
1
>>> len(Mock())
TypeError: object of type 'Mock' has no len()
>>> len(MagicMock())
0

E questi che potrebbero non essere così intuitivi (almeno non intuitivi per me):

>>> with MagicMock():
...     print 'hello world'
...
hello world
>>> MagicMock()[1]
<MagicMock name='mock.__getitem__()' id='4385349968'>

Puoi "vedere" i metodi aggiunti a MagicMock poiché questi metodi vengono richiamati per la prima volta:

>>> magic1 = MagicMock()
>>> dir(magic1)
['assert_any_call', 'assert_called_once_with', ...]
>>> int(magic1)
1
>>> dir(magic1)
['__int__', 'assert_any_call', 'assert_called_once_with', ...]
>>> len(magic1)
0
>>> dir(magic1)
['__int__', '__len__', 'assert_any_call', 'assert_called_once_with', ...]

Quindi, perché non usare sempre MagicMock?

La domanda che ti viene posta è: stai bene con le implementazioni predefinite del metodo magico? Ad esempio, va bene mocked_object[1]non sbagliare? Stai bene con conseguenze non intenzionali a causa delle implementazioni del metodo magico già presenti?

Se la risposta a queste domande è un sì, allora vai avanti e usa MagicMock. Altrimenti, attenersi a Mock.



3

Ho trovato un altro caso particolare in cui Simple Mock potrebbe diventare più utile di MagicMock:

In [1]: from unittest.mock import Mock, MagicMock, ANY
In [2]: mock = Mock()
In [3]: magic = MagicMock()
In [4]: mock.foo == ANY
Out[4]: True
In [5]: magic.foo == ANY
Out[5]: False

Il confronto con ANYpuò essere utile, ad esempio, confrontando quasi ogni chiave tra due dizionari in cui un certo valore viene calcolato usando un finto.

Questo sarà valido se stai usando Mock:


self.assertDictEqual(my_dict, {
  'hello': 'world',
  'another': ANY
})

mentre aumenterà un AssertionErrorse lo hai usatoMagicMock

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.