Я использую pythons mock.patch и хотел бы изменить значение возврата для каждого вызова. Вот предостережение: исправляемая функция не имеет входных данных, поэтому я не могу изменить возвращаемое значение на основе входных данных.
Вот мой код для справки.
def get_boolean_response():
response = io.prompt('y/n').lower()
while response not in ('y', 'n', 'yes', 'no'):
io.echo('Not a valid input. Try again'])
response = io.prompt('y/n').lower()
return response in ('y', 'yes')
Мой тестовый код:
@mock.patch('io')
def test_get_boolean_response(self, mock_io):
#setup
mock_io.prompt.return_value = ['x','y']
result = operations.get_boolean_response()
#test
self.assertTrue(result)
self.assertEqual(mock_io.prompt.call_count, 2)
io.prompt
это просто независимая от платформы (python 2 и 3) версия «input». В конечном счете, я пытаюсь смоделировать ввод пользователей. Я попытался использовать список для возвращаемого значения, но это не работает.
Вы можете видеть, что если возвращаемое значение является чем-то недопустимым, я просто получу бесконечный цикл здесь. Поэтому мне нужен способ в конечном итоге изменить возвращаемое значение, чтобы мой тест фактически завершился.
(Другой возможный способ ответить на этот вопрос - объяснить, как я могу имитировать пользовательский ввод в модульном тесте)
Не дублируйте этот вопрос главным образом потому, что у меня нет возможности варьировать входные данные.
Один из комментариев Ответа на этот вопрос находится в том же духе, но ответ / комментарий предоставлен не был.
источник
response is not 'y' or 'n' or 'yes' or 'no'
в не делать то , что вы думаете , что он делает. См. Как проверить одну переменную на несколько значений? и вы не должны использоватьis
для сравнения строковых значений, используйте==
для сравнения значений , а не идентификаторов объектов.is
для сравнения строковых литералов. Не делай этого. Тот факт, что это работает (иногда), является лишь деталью реализации в CPython. Кроме того,response is not 'y' or 'n' or 'yes' or 'no'
вероятно, не делает то, что вы думаете ...Ответы:
Вы можете назначить итерируемое значение
side_effect
, и mock будет возвращать следующее значение в последовательности каждый раз, когда оно вызывается:Цитирование
Mock()
документации :Кроме того, тест не
response is not 'y' or 'n' or 'yes' or 'no'
будет работать; Вы спрашиваете, является ли выражение истинным или истинным (всегда так, непустая строка всегда истинна) и т. д. Различные выражения по обе стороны от операторов независимы . См. Как проверить одну переменную на несколько значений?(response is not 'y')
'y'
or
Вы также не должны использовать
is
для проверки строки. Интерпретатор CPython может повторно использовать строковые объекты при определенных обстоятельствах , но это не то поведение, на которое вы должны рассчитывать.В качестве такового используйте:
вместо; это будет использовать тесты равенства (
==
), чтобы определить,response
ссылается ли строка на то же содержимое (значение).То же самое относится к
response == 'y' or 'yes'
; используйтеresponse in ('y', 'yes')
вместо.источник
mock
? Есть ли способ использовать патч с MagicMock, как я делаю со стандартным макетом?Mock
класса Stardard .m.side_effect = iter(['foo', 'bar', 'baz'])
).lambda
(функцию), а не aMagicMock
. Функциональный объект не может иметь свойств, поэтомуside_effect
атрибут должен быть итеративным. Вы не должны определять этот метод, хотя. Лучшее использованиеmock.patch.object(requests.Session, 'post')
; это приводит к объекту-патчеру, который правильно автоматически специфицирует метод иside_effect
правильно поддерживает .StopIteration
вызывается. Вы можете использовать любой итератор, так что вы можете использовать,itertools.chain(['Foo'], itertools.repeat('Bar'))
чтобы произвестиFoo
один раз, а затем создать всегдаBar
.