Правильный способ проверки сигналов Django - PullRequest
26 голосов
/ 29 сентября 2010

Я пытаюсь проверить отправленный сигнал, и он обеспечивает_args. Сигнал сработал внутри contact_question_create просмотра сразу после отправки формы.

Мой TestCase выглядит примерно так:

    def test_form_should_post_proper_data_via_signal(self):
        form_data = {'name': 'Jan Nowak'}
        signals.question_posted.send(sender='test', form_data=form_data)
        @receiver(signals.question_posted, sender='test')
        def question_posted_listener(sender, form_data):
            self.name = form_data['name']
        eq_(self.name, 'Jan Nowak')

Это правильный способ проверить этот сигнал? Есть идеи получше?

Ответы [ 6 ]

24 голосов
/ 12 мая 2015

Самый простой способ сделать то, что вы просили в 2015 году:

from unittest.mock import patch

@patch('full.path.to.signals.question_posted.send')
def test_question_posted_signal_triggered(self, mock):
    form = YourForm()
    form.cleaned_data = {'name': 'Jan Nowak'}
    form.save()

    # Check that your signal was called.
    self.assertTrue(mock.called)

    # Check that your signal was called only once.
    self.assertEqual(mock.call_count, 1)

    # Do whatever else, like actually checking if your signal logic did well.

И с этим вы только что проверили, что ваш сигнал сработал правильно.

11 голосов
/ 16 февраля 2015

У меня есть альтернативное предложение с использованием библиотеки mock, которая теперь является частью стандартной библиотеки unittest.mock в Python 3 (если вы используете Python 2, вам придется pip install mock).

try:
    from unittest.mock import MagicMock
except ImportError:
    from mock import MagicMock

def test_form_should_post_proper_data_via_signal(self):
    """
    Assert signal is sent with proper arguments
    """ 

    # Create handler
    handler = MagicMock()
    signals.question_posted.connect(handler, sender='test')

    # Post the form or do what it takes to send the signal
    signals.question_posted.send(sender='test', form_data=form_data)

    # Assert the signal was called only once with the args
    handler.assert_called_once_with(signal=signals.question_posted, form_data=form_data, sender="test")

Важная часть предложения состоит в том, чтобы смоделировать приемник, а затем проверить, передается ли ваш сигнал этому приемнику и вызывается только один раз.Это замечательно, особенно если у вас есть пользовательские сигналы или вы написали методы, которые отправляют сигналы, и вы хотите убедиться, что они отправляются в ваших модульных тестах.

5 голосов
/ 06 октября 2012

Вам необходимо:

  • утверждает, что сигнал был передан с правильными аргументами и ,
  • определенное количество раз и ,
  • в соответствующем порядке.

Вы можете использовать mock_django приложение, которое обеспечивает макет для сигналов .

Пример: * * один тысяча двадцать-одна

from mock import call


def test_install_dependency(self):
    with mock_signal_receiver(post_app_install) as install_receiver:
        self.env.install(self.music_app)
        self.assertEqual(install_receiver.call_args_list, [
            call(signal=post_app_install, sender=self.env,
                app=self.ukulele_app),
            call(signal=post_app_install, sender=self.env,
                app=self.music_app),
        ])
5 голосов
/ 29 сентября 2010

Я решил проблему самостоятельно. Я думаю, что лучшее решение следующее:

    def test_form_should_post_proper_data_via_signal(self):
        # define the local listener
        def question_posted_listener(sender, form_data, **kwargs):
            self.name = form_data['name']

        # prepare fake data
        form_data = {'name': 'Jan Nowak'}

        # connect & send the signal
        signals.question_posted.connect(question_posted_listener, sender='test')
        signals.question_posted.send(sender='test', form_data=form_data)

        # check results
        eq_(self.name, 'Jan Nowak')
4 голосов
/ 28 ноября 2010

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

0 голосов
/ 27 ноября 2010

Почему вы тестируете свой фреймворк?У Django уже есть модульные тесты для диспетчера сигналов.Если вы не верите, что ваш фреймворк в порядке, просто подключите его к вашему тестовому модулю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...