Burlándose de dos funciones con parche para una prueba unitaria.

Tengo una función que quiero que la prueba de unidad contenga llamadas a otras dos funciones. No estoy seguro de cómo puedo simular ambas funciones al mismo tiempo utilizando correctamente el parche. He proporcionado un ejemplo de lo que quiero decir a continuación. Cuando realizo pruebas de detección, las pruebas pasan, pero siento que debe haber una forma más limpia de hacerlo y realmente no entiendo la pieza con respecto a f.close () …

La estructura del directorio se ve así:

program/ program/ data.py tests/ data_test.py 

data.py:

 import cPickle def write_out(file_path, data): f = open(file_path, 'wb') cPickle.dump(data, f) f.close() 

data_test.py:

 from mock import MagicMock, patch def test_write_out(): path = '~/collection' mock_open = MagicMock() mock_pickle = MagicMock() f_mock = MagicMock() with patch('__builtin__.open', mock_open): f = mock_open.return_value f.method.return_value = path with patch('cPickle.dump', mock_pickle): write_out(path, 'data') mock_open.assert_called_once_with('~/collection', 'wb') f.close.assert_any_call() mock_pickle.assert_called_once_with('data', f) 

Resultados:

 $ nosetests . ---------------------------------------------------------------------- Ran 1 test in 0.008s OK 

Puede simplificar su prueba utilizando el decorador de parches y MagicMock así (son objetos MagicMock por defecto):

 @patch('cPickle.dump') @patch('__builtin__.open') def test_write_out(mock_open, mock_pickle): path = '~/collection' f = mock_open.return_value f.method.return_value = path write_out(path, 'data') mock_open.assert_called_once_with('~/collection', 'wb') mock_pickle.assert_called_once_with('data', f) f.close.assert_any_call() 

Las llamadas a una instancia de MagicMock devuelven una nueva instancia de MagicMock , por lo que puede verificar que el valor devuelto fue llamado como cualquier otro objeto simulado. En este caso f es un MagicMock denominado 'open()' (intente imprimir f ).

Además de la respuesta @Matti John, también puede usar el patch dentro de la función test_write_out :

 from mock import MagicMock, patch def test_write_out(): path = '~/collection' with patch('__builtin__.open') as mock_open, \ patch('cPickle.dump') as mock_pickle: f = mock_open.return_value ... 

Aquí hay un ejemplo simple sobre cómo probar el aumento de ConflictError en la función create_collection usando simulacro:

 import os from unittest import TestCase from mock import patch from ..program.data import ConflictError, create_collection class TestCreateCollection(TestCase): def test_path_exists(self): with patch.object(os.path, 'exists') as mock_method: mock_method.return_value = True self.assertRaises(ConflictError, create_collection, 'test') 

Por favor, también vea los documentos simulados y la impresionante introducción de Michael Foord a los simulacros .