Mock entire python class Mock entire python class python python

Mock entire python class


First it is very important to understand that you always need to Mock where it the thing you are trying to mock out is used as stated in the unittest.mock documentation.

The basic principle is that you patch where an object is looked up, which is not necessarily the same place as where it is defined.

Next what you would need to do is to return a MagicMock instance as return_value of the patched object. So to summarize this you would need to use the following sequence.

  • Patch Object
  • prepare MagicMock to be used
  • return the MagicMock we've just created as return_value

Here a quick example of a project.

connection.py (Class we would like to Mock)

class Connection(object):                                                            def execute(self):                                                                   return "Connection to server made"

file.py (Where the Class is used)

from project.connection import Connection                                        class FileRemoveOp(object):                                                          def __init__(self, foo):                                                             self.foo = foo                                                               def execute(self):                                                                   conn = Connection()                                                              result = conn.execute()                                                          return result    

tests/test_file.py

import unittest                                                                  from unittest.mock import patch, MagicMock                                       from project.file import FileRemoveOp                                            class TestFileRemoveOp(unittest.TestCase):                                           def setUp(self):                                                                     self.fileremoveop = FileRemoveOp('foobar')                                   @patch('project.file.Connection')                                                def test_execute(self, connection_mock):        # Create a new MagickMock instance which will be the        # `return_value` of our patched object                                             connection_instance = MagicMock()                                                connection_instance.execute.return_value = "testing"        # Return the above created `connection_instance`                             connection_mock.return_value = connection_instance                               result = self.fileremoveop.execute()                                             expected = "testing"                                                             self.assertEqual(result, expected)                                           def test_not_mocked(self):        # No mocking involved will execute the `Connection.execute` method                                                           result = self.fileremoveop.execute()                                             expected = "Connection to server made"                                           self.assertEqual(result, expected) 


I found that this simple solution works in python3: you can substitute a whole class before it is being imported for the first time. Say I have to mock class 'Manager' from real.manager

class MockManager:    ...import real.managerreal.manager.Manager = MockManager

It is possible to do this substitution in init.py if there is no better place.It may work in python2 too but I did not check.