mock python unit-testing mocking

python - Burlarse de una clase: Mock() o patch()?



mock install (2)

Estoy usando mock con Python y me preguntaba cuál de esos dos enfoques es mejor (léase: más pitónico).

Método uno : solo crea un objeto falso y úsalo. El código se ve así:

def test_one (self): mock = Mock() mock.method.return_value = True self.sut.something(mock) # This should called mock.method and checks the result. self.assertTrue(mock.method.called)

Método dos : use el parche para crear un simulacro. El código se ve así:

@patch("MyClass") def test_two (self, mock): instance = mock.return_value instance.method.return_value = True self.sut.something(instance) # This should called mock.method and checks the result. self.assertTrue(instance.method.called)

Ambos métodos hacen lo mismo. No estoy seguro de las diferencias.

¿Alguien podría iluminarme?


Tengo un video de YouTube sobre esto.

Respuesta corta: utiliza el mock cuando pases por el objeto del que te burlan, y el patch si no lo haces. De los dos, el simulacro es muy preferido porque significa que estás escribiendo código con una inyección de dependencia adecuada.

Ejemplo tonto:

# Use a mock to test this. my_custom_tweeter(twitter_api, sentence): sentence.replace(''cks'',''x'') # We''re cool and hip. twitter_api.send(sentence) # Use a patch to mock out twitter_api. You have to patch the Twitter() module/class # and have it return a mock. Much uglier, but sometimes necessary. my_badly_written_tweeter(sentence): twitter_api = Twitter(user="XXX", password="YYY") sentence.replace(''cks'',''x'') twitter_api.send(sentence)


mock.patch es un mock.patch muy diferente al mock.Mock . mock.Mock . patch reemplaza la clase con un objeto simulado y le permite trabajar con la instancia simulada. Eche un vistazo a este fragmento:

>>> class MyClass(object): ... def __init__(self): ... print ''Created MyClass@{0}''.format(id(self)) ... >>> def create_instance(): ... return MyClass() ... >>> x = create_instance() Created MyClass@4299548304 >>> >>> @mock.patch(''__main__.MyClass'') ... def create_instance2(MyClass): ... MyClass.return_value = ''foo'' ... return create_instance() ... >>> i = create_instance2() >>> i ''foo'' >>> def create_instance(): ... print MyClass ... return MyClass() ... >>> create_instance2() <mock.Mock object at 0x100505d90> ''foo'' >>> create_instance() <class ''__main__.MyClass''> Created MyClass@4300234128 <__main__.MyClass object at 0x100505d90>

patch reemplaza MyClass de una manera que le permite controlar el uso de la clase en las funciones que llama. Una vez que parchee una clase, las referencias a la clase se reemplazan por completo por la instancia simulada.

mock.patch generalmente se usa cuando prueba algo que crea una nueva instancia de una clase dentro de la prueba. mock.Mock instancias de mock.Mock son más claras y preferidas. Si su método self.sut.something creó una instancia de MyClass lugar de recibir una instancia como parámetro, entonces mock.patch sería apropiado aquí.