Search code examples
pythonunit-testingnosenosetestspython-unittest

Is it possible to patch a class instance with an existing Singleton instance?



I have a class representing our DB layer which is being instantiated internally in some classes (I cannot pass it as an outside parameter)
For example:

class MyClass(object):
    def __init__(self):
        self.dbapi = DatabaseAPI()
        self.timeout = 120

    def some_methods(self):
        pass

We're writing some Unit tests, and we'd like to mock the self.dbapi with an existing instance which we'll be creating before the test runs.

for example:

my_dbapi = DatabaseAPIMock()
...
...
@patch('MyModule.DatabaseAPI', my_dbapi)
def my_test(self):
    my_class = MyClass() #<---This is where I'm not able to mock the DatabaseAPI

This is what I tried to achieve so far, but from debugging the code I see that the self.dbapi is instantiated with the real object and not with the pre-made mock.

What am I missing?
BTW, we're running python 2.7

Thanks in advance!


Solution

  • You're patching the wrong thing. You need to patch in the module that is assigning the attribute, ie the one that contains the target class.

    It would be easier if you defined a method in your target class that gets your DatabaseAPI object. That way you can much more easily patch it.

    class MyClass(object):
        def __init__(self):
            self.dbapi = self.get_db_api()
            self.timeout = 120
    
        def get_db_api():
            return DatabaseAPI()
    

    and the test becomes:

    @patch('my_module.MyClass.get_db_api')
    def my_test(self, my_method):
        my_method.return_value = my_dbapi