I am trying to patch a class that is instantiated by the class I am trying to test, but it doesn't work. I have read the various docs but still haven't found what I am doing wrong. Here is the code snippet:
In tests/Test.py
:
from module.ClassToTest import ClassToTest
class Test(object):
@mock.patch('module.ClassToPatch.ClassToPatch', autospec = False)
def setUp(self, my_class_mock):
self.instance = my_class_mock.return_value
self.instance.my_method.return_value = "def"
self.class_to_test = ClassToTest()
def test(self):
val = self.class_to_test.instance.my_method() #Returns 'abc' instead of 'def'
self.assertEqual(val, 'def')
In module/ClassToPatch.py
:
class ClassToPatch(object):
def __init__(self):
pass
def my_method(self):
return "abc"
In module/ClassToTest.py
:
from module.ClassToPatch import ClassToPatch
class ClassToTest(object):
def __init__:
# Still instantiates the concrete class instead of the mock
self.instance = ClassToPatch()
I know in this case I could easily inject the dependency, but this is just an example. Also, we use a single class per file policy, with the file named like the class, hence the weird import naming.
unittest. mock provides a powerful mechanism for mocking objects, called patch() , which looks up an object in a given module and replaces that object with a Mock . Usually, you use patch() as a decorator or a context manager to provide a scope in which you will mock the target object.
unittest.mock is a library for testing in Python. It allows you to replace parts of your system under test with mock objects and make assertions about how they have been used. unittest.mock provides a core Mock class removing the need to create a host of stubs throughout your test suite.
In pytest , mocking can replace the return value of a function within a function. This is useful for testing the desired function and replacing the return value of a nested function within that desired function we are testing.
As norbert mentions, the fix is to change the mock line from
@mock.patch('module.ClassToPatch.ClassToPatch', autospec = False)
to
@mock.patch('module.ClassToTest.ClassToPatch', autospec = False)
According to the docs:
The patch() decorator / context manager makes it easy to mock classes or objects in a module under test. The object you specify will be replaced with a mock (or other object) during the test and restored when the test ends.
You are testing the ClassToTest
module, not the ClassToPatch
module.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With