Python Forum
Using Mock with python
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Using Mock with python
#1
Hello,

I need help to mock some Class/variable in python test. Here is the scenario:

app_client.py
class AppClient:
       
    def __init__(self):
        self.val = None
    
    def get_value(self, feature_eng):
....................................................

app_client_instance.py
from app_client import AppClient

app_client_instance = AppClient()
....................................................

from app_client_instance import app_client_instance

class FeatEng:

    @staticmethod
    def is_activ(feature_eng):
        client = app_client_instance
        value = client.get_value(feature_eng)
        return "true" == value
    
....................................................
unit test with magicMock

    def test_mockmag(self):
        client = MagicMock(spec=AppClient, name=AppClient)
        client.get_value.return_value = "false"
        instance = MagicMock(spec=app_client_instance)
        instance.app_client_instance.return_value = client
        result = FeatEng.is_activ("MIG_ENG")
I have a static class FeatEng importing a variable app_client_instance, this last creates an object of the AppClient class.
I want to mock app_client_instance and AppClient except FeatEng but it is not working. I don't know how to pass mocks to the FeatEng as no constructor on static class.

Have you a way to help?

Regards
Larz60+ write Oct-10-2021, 08:06 AM:
Please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.

Fixed for you this time. Please use bbcode tags on future posts,
Reply
#2
You need to pass the instance in as a function parameter then. That's what dependency injection is - you take the responsibility of supplying the dependency out of the class that uses it, so that you can substitute different implementations as necessary (like here for testing).

Also, do you really need to use MagicMock? I mean, it's pretty much straightforward to define a class that has the right method and returns the value you want:

class FakeClient:
    def get_value(self, feature_eng):
        return "true"
Since Python has duck typing, you don't need to worry about inheriting from AppClient
Reply
#3
app_client.py
-------------
class AppClient:
       
    def __init__(self):
        self.val = "true"
    
    def get_value(self, feature_eng):
        return self.val
....................................................

app_client_instance.py
----------------------
from app_client import AppClient

app_client_instance = AppClient()
....................................................

feat_eng.py
-----------
from app_client_instance import app_client_instance

class FeatEng:

    @staticmethod
    def is_activ(feature_eng):
        client = app_client_instance
        value = client.get_value(feature_eng)
        return "true" == value
    
....................................................
test.py
-------


import unittest
from unittest.mock import MagicMock
from app_client import AppClient
from app_client_instance import app_client_instance
from feat_eng import FeatEng

class FeatEngShould(unittest.TestCase):

    def test_mockmagshouldFalse(self):
        client = MagicMock(spec=AppClient, name=AppClient)
        client.get_value.return_value = "false"
        instance = MagicMock()
        instance.app_client_instance.return_value = client
        result = FeatEng.is_activ("MIG_ENG")
        self.assertFalse(result) 
Error:
Output:
$ pytest test.py ================================================================================== test session starts =================================================================================== platform darwin -- Python 3.8.2, pytest-6.2.1, py-1.10.0, pluggy-0.13.1 rootdir: /Users/hocinema/projets/scripts/python plugins: hypothesis-5.43.3, anyio-2.0.2 collected 1 item test.py F [100%] ======================================================================================== FAILURES ======================================================================================== _______________________________________________________________________________ FeatEngShould.test_mockmag _______________________________________________________________________________ self = <test.FeatEngShould testMethod=test_mockmag> def test_mockmag(self): client = MagicMock(spec=AppClient, name=AppClient) client.get_value.return_value = "false" instance = MagicMock() instance.app_client_instance.return_value = client result = FeatEng.is_activ("MIG_ENG") > self.assertFalse(result) E AssertionError: True is not false test.py:16: AssertionError ================================================================================ short test summary info ================================================================================= FAILED test.py::FeatEngShould::test_mockmag - AssertionError: True is not false =================================================================================== 1 failed in 0.21s ====================================================================================
I want to make the mock client returning false to make success the test but instead it failed
Reply
#4
Anything else to implement magicMock with static class?
Reply
#5
I found the solution by only mocking the decorated static method.
I also initialized the method variables with mocked values, et redefined the method returned value.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020