["python","unit-testing","testing","mocking","nose"]
Mocking two functions with patch for a unit test

I have a function I want to unit test contains calls two other functions. I am unsure how can I mock both functions at the same time properly using patch. I have provided an example of what I mean below. When I run nosetests, the tests pass but I feel that there must be a cleaner way to do this and I do not really Understand the piece regarding f.close()... The directory structure looks like this: 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) Results: $ nosetests . ---------------------------------------------------------------------- Ran 1 test in 0.008s OK
You can simplify your test by using the patch decorator and nesting them like so (they are MagicMock objects by default): from unittest.mock import patch @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() Note that, as shown in the example above, the decorators are applied bottom-up in the order of the parameters. See the quick guide from the docs for official documentation of this. Calls to a MagicMock instance return a new MagicMock instance, so you can check that the returned value was called just like any other mocked object. In this case f is a MagicMock named 'open()' (try printing f).