Sreeram TP
Sreeram TP

Reputation: 11937

pytest mock a function call in __init__ of a class

I have a class like this,

from external_package.module.sub_module import fun

class MyClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.z = fun()
        
    def printer(self):
        print(f"X : {self.x}, y : {self.y}, z: {self.z}")

I want to write a unit test for this class and mock the function call that is happening in the init method.

I have tried patching like this,

from external_package.module import sub_module
    
def test_my_class(mocker):

    mocker.patch.object(sub_module, 'fun', return_value="this is mocked")
    obj = MyClass(10, 20)
    
    assert obj.z == "this is mocked"

But I can see that the call is not patched and a function call happens in the init method.

How can I patch the call with pytest-mock or any other mocking packages?

Upvotes: 3

Views: 7807

Answers (2)

daniboy000
daniboy000

Reputation: 1129

You should mock your function with the path where it's been used and not it's original path or location. In the example bellows it's defined that the fun method in the object MyClass will be mocked and the returned value will be "this is mocked".

from external_package.module import sub_module
from my_class import MyClass

def test_my_class(mocker):

    mocker.patch.object(MyClass.submodule, 'fun', return_value="this is mocked")
    obj = MyClass(10, 20)
    
    assert obj.z == "this is mocked"

Check this link for some good examples of how to mock objects in Python.

Upvotes: 2

Sreeram TP
Sreeram TP

Reputation: 11937

I was able to solve this by slightly changing the import statement in the source code,

from external_package.module import sub_module 

class MyClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.z = sub_module.fun()
        
    def printer(self):
        print(f"X : {self.x}, y : {self.y}, z: {self.z}")

Note that I'm importing submodule and calling method from the imported sub_module.

Now, in the test I used the pytest-mock fixture like this,

import external_package
    
def test_my_class(mocker):

    method = mocker.patch("external_package.module.sub_module.fun")
    method.return_value = "this is mocked"

    obj = MyClass(10, 20)
    
    assert obj.z == "this is mocked"

I'm not sure why this worked and not the earlier approach. Hope someone can clear that.

Upvotes: 0

Related Questions