Как проверить исключение в сигнале?

У меня есть сигнал:

create_flat_referral = django.dispatch.Signal(providing_args=["request", "user"])

И у меня есть ресивер:

@receiver(create_flat_referral, sender=None)
def save_flat_referral(sender, request, user, **kwargs):

    referral_link = request.POST.get('referral', None)
    if not referral_link:
        referral_link = request.GET.get('ref', None)

    try:
        if referral_link:
            link = Link.objects.get(token = referral_link)
            referral = FlatReferral.objects.create(
                referrer = link.user,
                referred = user
            )
    except Link.DoesNotExist:
        logger.exception('...')
    except ValidationError:
        logger.exception('...')

Я хочу охватить тестами все исключения.

Как проверить исключение в сигнале?

В дополнение к тому, что я хочу получить assertRaises, я также хочу получить assertRaisesMessage

Как лучше всего это сделать?

Если я пытаюсь сделать что-то вроде этого:

    self.assertRaises(
        ValidationError,
        lambda: signals.create_flat_referral.send(
            sender = None,
            request = post_request,
            user = self.referred
        )
    )

Что я провалил тест:

AssertionError: ValidationError not raised by lambda

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
99
2

Ответы 2

AssertionError: ValidationError not raised by lambda

Определение, в котором callable - это имя функции, а не вызов функции

`assertRaises(exception, callable, *args, **kwds)`

например, это будет работать, поскольку cal_exp - это имя функции

 self.assertRaises(OverflowError, MathOverFlow().cal_exp, 2)

Это не сработает, так как cal_exp(2) недействителен для assert

 self.assertRaises(OverflowError, MathOverFlow().cal_exp(2))

Я лично предпочитаю такой способ:

d = {'sender': None, 'request': post_request, 'user': self.referred}

with self.assertRaises(ValidationError):
    signals.create_flat_referral.send(**d)

ИЛИ имя функции с **kwargs, а не func(**kwargs)

self.assertRaises(ValidationError, signals.create_flat_referral.send, **d)

Я не могу найти место для lamda, или, по крайней мере, он усложнил здесь вещи больше, чем нужно.

Вам нужно протестировать сам обработчик сигналов, а не структуру сигналов Django (которая тщательно проверена самим Django). Таким образом, вам не нужно проходить через все проблемы с запуском фактического сигнала - вы можете просто вызвать свою функцию напрямую с смоделированными параметрами и проверить, правильно ли она их обрабатывает - что-то вроде этого:

from django.test import TestCase, RequestFactory

class MySignalTestCase(TestCase):

    def test_link_does_not_exist(self):
        # Create a dummy request that you can give to your signal handler
        factory = RequestFactory()
        request = factory.post('/')   # Pass appropriate params here if needed

       with self.assertRaises(ValidationError):
           # sender isn't used, hence you can just pass None there.
           save_flat_referral(sender=None, request=request)

Другие вопросы по теме