Search code examples
pythonpython-3.xmagicmock

Mocking dependencies


I am Python newbie and trying to understand how to mock methods in UTs.

Here is my Test test_module2.py

from module2 import A
import unittest

from unittest.mock import patch, MagicMock

class TestBulkLoad(unittest.TestCase):

    @patch('simple_module.SimpleModuleClass')
    def test_fun(self, a):
        a.simpleFun = MagicMock(return_value=3)

        testA = A()
        testA.fun()

        assert a.simpleFun.called

and I want to check that dependent SimpleModuleClass was mocked and invoked

module2.py

from simple_module import SimpleModuleClass


class A:
    def fun(self):
        print('I am from A class')

        thing = SimpleModuleClass()
        thing.simpleFun()

        return -1

simple_module.py

class SimpleModuleClass:
    def simpleFun(self):
        print("I am from SimpleModuleClass")
        return 0

I get AssertionError. Could you help me understand how to fix this?


Solution

  • a.simpleFun = MagicMock(return_value=3)

    This line is only modifying the method of your mock object a (which you really should rename simpleModuleMock, since it's a mock of a SimpleModule class and not an A). It doesn't mock every instance of SimpleModule everywhere in your code, hence why an instance of SimpleModule is instantiated in A.fun() and not an instance of a mock of SimpleModule.

    I would use dependency injection and pass an instance of SimpleModule to A.fun() instead of instantiating it inside of it, so that you can pass a mock. You could also make thing a public variable like so:

    test_module2.py:

    class TestBulkLoad(unittest.TestCase):
        @patch('simple_module.SimpleModuleClass')
        def test_fun(self, simpleModuleMock):
            simpleModuleMock.simpleFun = MagicMock(return_value=3)
    
            testA = A()
            A.thing = simpleModuleMock
            assert(testA.fun() == -1)
    
            # assert simpleModule.simpleFun.called
            assert isinstance(simpleModuleMock.simpleFun, MagicMock)
    

    module2.py:

    class A:
        thing = SimpleModuleClass()
        def fun(self):
            print('I am from A class')
            self.thing.simpleFun()
            return -1
    

    Note that there may exist better solutions with Python, but if there are, 1. I don't know of them, and 2. I doubt they're good practice.