Тестирование функции генератора имеет странное поведение - PullRequest
0 голосов
/ 17 марта 2019

Я обнаружил странное поведение, связанное с тестированием функций генератора. Я предполагаю, что есть причина этого, но я не понимаю, что. Это мой код:

class Foo:
    def foo_function(self):
        return range(10)

class Client:
    def __init__(self):
        self.client = Foo()

    def baz(self):
        for i in self.client.foo_function():
            yield i

А это мой тест:

from unittest.mock import patch

from django.test import TestCase

from my_app.my_module.client import Client


class ClientTestCase(TestCase):

    @patch('my_app.my_module.client.Foo')
    def test_baz(self, foo):
        client = Client('')
        client.baz()

        foo().foo_function.assert_called_once()

Когда я запускаю этот тест, я получаю AssertionError:

AssertionError: Expected 'foo_function' to have been called once. Called 0 times.

, что может быть только моей ошибкой, но как только я пытаюсь отладить с pdb, я вижу странное поведение. Если я поместил след внутри foo_function, я понял, что он никогда не попадет внутрь него. Так что, поместив трассировку прямо перед вызовом и включив ее, я получаю GeneratorExit и оставляет:

[28] > /app/my_app/my_module/tests/test_client.py(14)test_baz()
-> client.baz()
   6 frames hidden (try 'help hidden_frames')
(Pdb++) step
--Call--
[29] > /app/my_app/my_module/client.py(11)foo_function()
-> def foo_function(self):
   6 frames hidden (try 'help hidden_frames')
(Pdb++) next
GeneratorExit
[29] > /app/my_app/my_module/client.py(11)foo_function()
-> def foo_function(self):
   6 frames hidden (try 'help hidden_frames')
(Pdb++)

Я уверен, что это также не связано с издевательством, потому что я вносил изменения, чтобы попытаться понять, что происходит, но я до сих пор не могу найти причину. Кто-нибудь знает, что это происходит? И если да, то как я могу проверить такую ​​функцию? Спасибо!

1 Ответ

0 голосов
/ 17 марта 2019

Вызов client.baz() создает генератор.Генераторы не выполняют никакого кода, пока вы не начнете их перебирать.

Измените client.baz() на next(client.baz()), и ваш тест пройдет.

...