Я тестирую относительно простой кусок кода, который использует два относительно сложных объекта, требующих доступа к диску.Сложные объекты из библиотеки.Я хотел бы посмеяться над этими объектами библиотеки и утверждать, что некоторые из их функций-членов были вызваны с конкретными значениями, в зависимости от ввода.
Вызовы, которые я использую, зависят от некоторого внутреннего состояния объектов библиотеки.Я осознаю, что могу смоделировать каждый вызов функции на сложных объектах индивидуально и установить return_value
перед каждым.Это кажется намного более запутанным и болезненным, чем нужно.
Кажется, что вы должны иметь возможность предоставить собственный класс и обернуть его объектом Mock для отслеживания всех вызовов функций-членов.Я потратил несколько часов, пытаясь разобраться в официальной документации , и самый близкий мне аргумент wraps
.К сожалению, кажется, что это не заменяет все члены на mock, которые обертывают, вместо этого, он просто использует переменные-члены mock объекта, отслеживая только вызовы к __init__
.
, например, в module_a.py:
# Assuming some library class that acts something like this:
class A:
def __init__(self, filename):
self.filename = filename
def get(self):
# ... Some complicated code, involving state and disk access ...
return something
def some_fnc(filename):
a = A(filename)
a.get()
a.get()
a.get()
a.get()
in test_module_a.py:
import unittest
import unittest.mock
import module_a
class MockA:
def __init__(self, *args, **kwargs):
self.i = 0
pass
def get(self):
# Fake version that returns dummy values,
# but more complicated than simply returning some value.
# Easy to reason about. If this gets complicated then you have problems.
print(self.i, 'is gotten')
if self.i > 3:
return 5
self.i += 1
return 1
class SomeFncTestCase(unittest.TestCase):
@unittest.mock.patch('module_a.A', wraps=MockA)
def test_it(self, m):
module_a.some_fnc('in_file')
m.assert_called_with('in_file')
m.get.assert_called()
MockA.get вызывается, и первое утверждение проходит, ноВторой assert терпит неудачу.
Есть некоторые функции, которые я пропускаю?Можно ли делать то, что я хочу?Есть ли причина, почему то, что я предлагаю, особенно плохо?