Skip to content Skip to sidebar Skip to footer

Python3 Mock Doesn't Work For All Paths

The Production file (production_file.py) is: class MyError(Exception): pass class MyClass: def __init__(self): self.value = None def set_value(self, value):

Solution 1:

If you are running test.py as __main__ then it is not test.MyClass it would be __main__.MyClass, or in both cases __name__+".MyClass".

I was able to determine that the class used and the class patched were different by adding a print statement:

classCaller:
    defbar(self, smth):
        print(MyClass) #lets see what we are actually making an instance of...
        obj = MyClass()
        ...

When the patch is applied to the class that this is using you would see something like this:

<MagicMock name='MyClass' spec='MyClass'id='4387629656'>

But when the class in moved into test.py you will see something like:

<class'__main__.MyClass'>

Which indicates:

  1. There was no patching applied to MyClass (at least the one that is used for the test.)
  2. The name of the class that needs to be patched is __main__.MyClass

However It is quite likely that your "more... complicated situation" is not working because of a setup like this:

from production_file import MyClass

classMyError(Exception):
    passclassCaller:
    defbar(self, smth):
        print(MyClass)
        obj = MyClass()
        ...

classMyTest(unittest.TestCase):
    deftest_caller(self):
        with patch('production_file.MyClass', autospec=MyClass) as MyClassMock:
            ...

In this case production_file.MyClass is being patched and MyClass is being imported from production_file so the correct class is being patched but still the output is:

<class'production_file.MyClass'>

This is because the Class was directly imported to the local namespace, so when the patch is applied to the production_file the local namespace is still unaffected, we can check that the patch was actually applied with:

...
defbar(self, smth):
    print(MyClass)
    from production_file import MyClass as pf_MyClass
    print(pf_MyClass)
...


#output:
<class'production_file.MyClass'>
<MagicMock name='MyClass' spec='MyClass'id='4387847136'>

If this is the case you just need to import the module, not the class directly. Then once the patch is applied you will be using it right from the file:

import production_file

...
classCaller:
    defbar(self, smth):
        print(production_file.MyClass)
        obj = production_file.MyClass()
        ...

classMyTest(unittest.TestCase):
    deftest_caller(self):
        with patch('production_file.MyClass', autospec=MyClass) as MyClassMock:
            ...

Post a Comment for "Python3 Mock Doesn't Work For All Paths"