How to mock.patch a class imported in another module

PythonUnit Testing

Python Problem Overview


I have a python class with such a module:

xy.py

from a.b import ClassA

class ClassB:
  def method_1():
    a = ClassA()
    a.method2()

then I have ClassA defined as:

b.py

from c import ClassC

class ClassA:
  def method2():
      c = ClassC()
      c.method3()

Now in this code, when writing test for xy.py I want to mock.patch ClassC, is there a way to achieve that in python?

obviously I tried:

mock.patch('a.b.ClassA.ClassC')

and

mock.patch('a.b.c.ClassC')

None of these worked.

Python Solutions


Solution 1 - Python

You need to patch where ClassC is located so that's ClassC in b:

mock.patch('b.ClassC')

Or, in other words, ClassC is imported into module b and so that's the scope in which ClassC needs to be patched.

Solution 2 - Python

Where to patch: > patch() works by (temporarily) changing the object that a name points to with another one. There can be many names pointing to any individual object, so for patching to work you must ensure that you patch the name used by the system under test. > > The basic principle is that you patch where an object is looked up, which is not necessarily the same place as where it is defined.

In your case, the lookup location is a.b.ClassC since you want to patch ClassC used in ClassA.

import mock

with mock.patch('a.b.ClassC') as class_c:
    instance = class_c.return_value  # instance returned by ClassC()
    b = ClassB()
    b.method1()
    assert instance.method3.called == True
    

Solution 3 - Python

Each time the method ClassA().method2() is called, the method looks up ClassC as a global, thus finding ClassC in the a.b module. You need to patch that location:

mock.patch('a.b.ClassC')

See the Where to patch section section.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAnkitView Question on Stackoverflow
Solution 1 - PythonSimeon VisserView Answer on Stackoverflow
Solution 2 - PythonsirfzView Answer on Stackoverflow
Solution 3 - PythonMartijn PietersView Answer on Stackoverflow