У меня есть сигнал:
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






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)