Издевайтесь над итератором, чтобы вызвать исключение - PullRequest
0 голосов
/ 03 апреля 2019

Я использую python 2.7.15rc1 .Я пытаюсь смоделировать итератор, чтобы он генерировал исключение при итерации по нему.Например:

elements = [1,2,3,Exception('boom!')]
iterable = <create a mock iterable to iterate over "elements">

# this does not print anything.
for value in iterable:
   ...

Я пытался использовать атрибут side_effect в методе next() экземпляра MagicMock, например так:

from mock import MagicMock

mocked_next = MagicMock()
mocked_next.next.side_effect = [1,2,3,Exception('boom!')]

mocked_iterable = MagicMock()
mocked_iterable.__iter__.return_value = mocked_next
...
# This does not print anything and no exception is raised
for value in mocked_iterable:
    print(value)

Я предположил, что *Цикл 1012 * в конечном итоге вызовет __iter__ для mocked_iterable, который вернет другой фиктивный объект с атрибутом next, имеющим side_effect.Я ожидал, что цикл в итоге вызовет mocked_next.next(), который будет повторять список, который я ему предоставил в side_effect.

Очевидно, мое понимание неверно.Что мне здесь не хватает?Может ли это быть достигнуто исключительно с помощью mock, или мне нужно создать собственный итератор для реализации этого поведения?

EDIT: Я пытаюсь протестировать часть обработки исключений частикод, который выполняет итерацию и, следовательно, пытается эмулировать итератор, выдавая исключение.

1 Ответ

1 голос
/ 03 апреля 2019

То, что вы ищете, не подходит для MagicMock, поскольку side_effect может быть либо исключением, либо итерацией, но не обоими. Вместо этого вы должны создать класс с методом __iter__, который возвращает элементы в данной последовательности, а затем вызывает указанное исключение:

class ExceptionRaisingIterable:
    def __init__(self, seq, exception):
        self.seq = seq
        self.exception = exception

    def __iter__(self):
        for i in self.seq:
            yield i
        raise self.exception

for value in ExceptionRaisingIterable([1, 2, 3], Exception('boom!')):
    print(value)

Это выводит:

1
2
3
Traceback (most recent call last):
  File "test.py", line 11, in <module>
    for value in ExceptionRaisingIterable([1, 2, 3], Exception('boom!')):
  File "test.py", line 9, in __iter__
    raise self.exception
Exception: boom!
...