Как mock.patch класс, импортированный в другой модуль

У меня есть класс python с таким модулем:

xy.py

from a.b import ClassA

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

то у меня есть ClassA, определяемый как:

b.py

from c import ClassC

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

Теперь в этом коде при написании теста для xy.py я хочу mock.patch ClassC, есть ли способ достичь этого в python?

Очевидно, я пробовал:

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

и

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

Ни один из них не работал.

Ответ 1

Вам нужно запланировать, где ClassC находится так, что ClassC в b:

mock.patch('b.ClassC')

Или, другими словами, ClassC импортируется в модуль b и так, чтобы область, в которой ClassC должна быть исправлена.

Ответ 2

Где патчить:

patch() работает (временно) изменяя объект, на который указывает имя, с другим. Может быть много имен, указывающих на любой отдельный объект, поэтому для исправления необходимо убедиться, что вы исправили имя, используемое тестируемой системой.

Основной принцип заключается в том, что вы исправляете, где объект ищется, что не обязательно совпадает с местом, где он определен.

В вашем случае местоположение поиска - a.b.ClassC, так как вы хотите установить патч ClassC, используемый в 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

Ответ 3

Каждый раз, когда вызывается метод ClassA().method2(), метод просматривает ClassC как глобальный, тем самым нахождение ClassC в модуле a.b. Вам необходимо исправить это местоположение:

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

См. раздел Где поместить раздел.