Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 
like image 607
cnodell Avatar asked Apr 02 '13 11:04

cnodell


People also ask

What can be mocked for unit testing?

What is mocking? Mocking is a process used in unit testing when the unit being tested has external dependencies. The purpose of mocking is to isolate and focus on the code being tested and not on the behavior or state of external dependencies.

What is mock patch?

mock provides a powerful mechanism for mocking objects, called patch() , which looks up an object in a given module and replaces that object with a Mock . Usually, you use patch() as a decorator or a context manager to provide a scope in which you will mock the target object.

What is the difference between mock and MagicMock?

With Mock you can mock magic methods but you have to define them. MagicMock has "default implementations of most of the magic methods.". If you don't need to test any magic methods, Mock is adequate and doesn't bring a lot of extraneous things into your tests.

What is mocking in unit testing Python?

What is mocking in Python? Mocking in Python means the unittest. mock library is being utilized to replace parts of the system with mock objects, allowing easier and more efficient unit testing than would otherwise be possible.


1 Answers

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() 

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).

like image 53
Matti John Avatar answered Sep 28 '22 19:09

Matti John