Python Unittest Mocking Constructors

Writing unit tests should be easy. If I spend effort and time writing unit tests, I’m not sure I’ll write a lot.

Let’s be honest: mocks are the worst part. And how many times did I need to mock a constructor? Enough to know it isn’t easy and write down an article.

Why is mocking constructors such a pain? Well, because constructors work differently, it’s like static method. Let’s see the details.

Problem When Mocking A Constructor With Unittest

Let’s see an example of production code.

from core.my_package import AnotherClass

def my_method():
    instance = AnotherClass()
    return instance.call()

I want to mock the class AnotherClass because it’s already tested in its own test class. So, let’s only verify that I call the method call().

@patch("core.my_package.AnotherClass", new=lambda: fake_my_method)
def test_my_method():
    result = my_method()
    assert 1 == result
    

A simple solution would be using the @patch decorator using the constructor. But when running this, unittest doesn’t mock the constructor at all. What wrong?

The Solution To Mock A Constructor With Unittest

In fact, the way unittest manages the imports is not easy. The only way I found was modifying how I import the class into my method to test.

from core import my_package

def my_method():
    instance = my_package.AnotherClass()
    return instance.call()

Instead of importing the class in the import line, I need to import the module in the import line. And when instantiating the class, use the module as prefix.

@patch("core.my_package.AnotherClass", new=lambda: fake_my_method)
def test_my_method():
    result = my_method()
    assert 1 == result
    

The path annotation should now work perfectly.


Discover more from The Dev World – Sergio Lema

Subscribe to get the latest posts sent to your email.


Comments

Leave a comment