Ответ 1
Хорошо, оказывается, что хороший ночной сон и холодный душ заставили меня переосмыслить всю проблему. Я все еще очень новичок в концепции насмешек, поэтому он все еще не совсем потоплен.
Дело в том, что нет необходимости переопределять патч для издевающегося объекта. Это насмешливый объект, и это означает, что я могу заставить его сделать что угодно. Поэтому моя первая попытка:
@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):
def test_override(self):
method_to_patch.return_value = 2
(....)
Это сработало, но имело побочный эффект изменения возвращаемого значения для всех следующих тестов. Итак, я попробовал:
@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):
def test_override(self):
method_to_patch.return_value = 2
(....)
method_to_patch.return_value = 1
И это сработало как шарм. Но, похоже, слишком много кода. Итак, я пошел по пути управления контекстом, например:
@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):
def test_override(self):
with mock.patch('method_to_patch', mock.Mock(return_value=2):
(....)
Я думаю, что это кажется более ясным и более кратким.
О порядке, в котором применяются декораторы patch
, это фактически правильный порядок. Так же, как штабелированные декораторы применяются снизу вверх, предполагается, что декоратор метода должен быть вызван перед декоратором класса. Я предполагаю, что это имеет смысл, я просто ожидал противоположного поведения.
В любом случае, я надеюсь, что это поможет некоторым бедным новичкам, таким как моя в будущем.