Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use mock_open() with patch.object() in test annotation

I'm trying to mock read from file. Using examples it can be done with a construction like:

with patch('__builtin__.open', mock_open(read_data='1'), create=True) as m:
    with open('foo') as h:
        result = h.read()

I wonder, is there a way to mock open function using my testcase annotation. Like:

@patch.object(__builtin__, 'open')
def test_check_status_running(self, m_open):

I don't find the correct way, because for me it works for int and doesn't work for strings:

@patch.object(__builtin__, 'open')
def test_check_status_running1(self, m_open):
    m_open = mock_open(read_data='1')
    pid = open('testfile').read().strip()
    print type(pid)                    # <class 'mock.MagicMock'>
    self.assertEqual(1, int(pid))      # Pass
    self.assertEqual('1', pid)         # Fails MismatchError: '1' != <MagicMock name='open().read()' id='39774928'>
like image 714
Gwen Avatar asked Sep 18 '13 08:09

Gwen


People also ask

What does patch do in Unittest?

patch() unittest. 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?

Mock vs. So what is the difference between them? MagicMock is a subclass of Mock . It contains all magic methods pre-created and ready to use (e.g. __str__ , __len__ , etc.). Therefore, you should use MagicMock when you need magic methods, and Mock if you don't need them.


1 Answers

You can patch the open method in many ways. I prefer to patch the builtins.open and to pass the mocked object to the test method like this:

from unittest.mock import patch, mock_open
from mymodule import method_that_read_with_open

class TestPatch(unittest.TestCase):
    @patch('builtins.open', new_callable=mock_open, read_data='1')
    def test_open_file(self, m):
        string_read = method_that_read_with_open()
        self.assertEqual(string_read, '1')
        m.assert_called_with('filename', 'r')

Note that we are passing the mock_open function without calling it!

But because you are patching the builtin method, you can also do:

class TestPatch(unittest.TestCase):
    @patch('builtins.open', mock_open(read_data='1'))
    def test_open_file(self):
        string_read = method_that_read_with_open()
        self.assertEqual(string_read, '1')
        open.assert_called_with('filename', 'r')

This two examples are basically equivalent: in the first one we are giving to the patch method a factory function that he will invoke to create the mock object, in the second one we are using an already created object as argument.

like image 186
Genma Avatar answered Nov 09 '22 23:11

Genma