У меня есть класс с дорогой функцией __init__
. Я не хочу, чтобы эта функция вызывалась из тестов.Избегайте выполнения __init__ из издевающегося класса
Для этого примера я сделал класс, который вызывает исключение в __init__
:
class ClassWithComplexInit(object):
def __init__(self):
raise Exception("COMPLEX!")
def get_value(self):
return 'My value'
У меня есть второй класс, который создает экземпляр ClassWithComplexInit
и использует его функции.
class SystemUnderTest(object):
def my_func(self):
foo = ClassWithComplexInit()
return foo.get_value()
Я пытаюсь написать несколько модульных тестов вокруг SystemUnderTest#my_func()
. Проблема, с которой я сталкиваюсь, неважно, как я пытаюсь высмеять ClassWithComplexInit
, функция __init__
всегда выполняется и исключение возникает.
class TestCaseWithoutSetUp(unittest.TestCase):
@mock.patch('mypackage.ClassWithComplexInit.get_value', return_value='test value')
def test_with_patched_function(self, mockFunction):
sut = SystemUnderTest()
result = sut.my_func() # fails, executes ClassWithComplexInit.__init__()
self.assertEqual('test value', result)
@mock.patch('mypackage.ClassWithComplexInit')
def test_with_patched_class(self, mockClass):
mockClass.get_value.return_value = 'test value'
sut = SystemUnderTest()
result = sut.my_func() # seems to not execute ClassWithComplexInit.__init__()
self.assertEqual('test value', result) # still fails
# AssertionError: 'test value' != <MagicMock name='ClassWithComplexInit().get_value()' id='4436402576'>
Второй подход выше является тот, который я получил от this similar Q&A, но это не сработало. Это показалось, чтобы не запускать функцию __init__
, но мое утверждение терпит неудачу, потому что результат заканчивается тем, что является экземпляром mock, а не моим значением.
Я также попытался настроить patch
экземпляр в функции setUp
, используя start
и stop
функции, как the docs suggest.
class TestCaseWithSetUp(unittest.TestCase):
def setUp(self):
self.mockClass = mock.MagicMock()
self.mockClass.get_value.return_value = 'test value'
patcher = mock.patch('mypackage.ClassWithComplexInit', self.mockClass)
patcher.start()
self.addCleanup(patcher.stop)
def test_my_func(self):
sut = SystemUnderTest()
result = sut.my_func() # seems to not execute ClassWithComplexInit.__init__()
self.assertEqual('test value', result) # still fails
# AssertionError: 'test value' != <MagicMock name='mock().get_value()' id='4554658128'>
Это также, кажется, чтобы избежать моей __init__
функции, но значение я устанавливаю для get_value.return_value
не соблюдается и get_value()
по-прежнему возвращает MagicMock
экземпляр.
Как я могу издеваться над классом со сложным __init__
, который был создан моим тестируемым кодом? В идеале я хотел бы получить решение, которое хорошо подходит для многих модульных тестов в классе TestCase (например, не нужно до patch
каждый тест).
Я использую версию Python 2.7.6
.
Как вы можете использовать ClassWithComplexInit для вашего тестового скрипта? 'from mypackage import ClassWithComplexInit' или что-то еще? – chepner
@chepner Мой тестовый скрипт даже не импортировал 'ClassWithComplexInit'. Я переключил кучу кода с моего реального кода, чтобы опубликовать здесь на SO и испортил ссылки на пакеты, я понимаю, что ссылка неверна.Вы обращаетесь к этому в своем ответе, хотя, спасибо! –