7
votes

Tests que j'ai connecté à un signal particulier à Django

J'ai une application Django appelée "Publisher", elle se connecte à divers signaux dans mon projet Django, et lorsqu'il leur reçoit, il envoie un message à une file de la RabbitMQ. Ce que je veux faire, c'est être capable de tester que mon code de configuration se connecte aux signaux corrects.

Ma structure d'application ressemble à: xxx

mon __init__.py ressemble à: xxx

et mes signaux.pycycxxx a pensé à corriger la fonction du récepteur et à vérifier que la simulation a été appelée lorsque j'ai envoyé le signal:

tests.py: xxx

Cependant, car le module de signaux est importé et donc les connexions de signaux sont fabriqués avant que les tests soient exécutés, cette approche ne fonctionne pas car les connexions sont faites avant que la fonction soit corrigée ......

Quelqu'un peut-il suggérer une stratégie alternative?


1 commentaires

Je ne sais pas si je reçois cette ligne droite mais je suive mes signaux écrivant à un journal dans la fonction de récepteur defeiver_function (* args, ** kwargs):


4 Réponses :


16
votes

J'ai couru dans le même problème moqueur que vous décrivez. Ma solution consiste à atteindre le registre des signaux de Django et à affirmer que ma fonction a été enregistrée auprès du signal correct.

Voici mon test: xxx

Un peu d'explication sur cette compréhension de cette liste :

"Pre_Delete" est l'instance de django.dispatch.dispatcher.signal que je me suis soucié dans ce cas. Vous utiliseriez votre propre "my_interresting_signal" dans votre exemple. Les signaux ont une propriété interne appelée "Récepteurs", c'est une liste de deux tuples, où le deuxième élément est une faiblesse sur la fonction que vous vous enregistrez (donc r [1]). Appeler un affaife retourne le référent.

Je devais jouer avec des faiblesses pour comprendre cela beaucoup: xxx

espère que cela aide cela aide.


3 commentaires

Je ne pense pas que cela soit tout à fait raison. Si bar_func est dans modèles.py alors, oui, qui sera automatiquement importé par Django et donc connecté au signal. Mais si c'est dans un signals.py alors ce ne sera pas nécessairement. En outre, l'acte d'importer votre réceptionnement dans le test le connectera automatiquement, de sorte que le test passera même si vous ne le connecte pas ailleurs.


@seddonyonyonyonyonyonyy Très bons points, mais techniquement, vous devez toujours utiliser un appconfig pour enregistrer les signaux (ou faire les importations), donc je suppose que vous pouvez supposer en toute sécurité qu'au moins cela se passe. Donc peut-être un autre test pour s'assurer que AppConfig enregistre vos récepteurs?


Pas une mauvaise idée!



4
votes

Un moyen de tester si le signal est connecté le déconnecte et vérifie le résultat de cette action. Appeler .disconnect (...) renvoie vrai si le signal a été déconnecté ou false sinon.

Par exemple nous Voulez-vous tester que le signal post_save est connecté à notre récepteur_function .

modules.py xxx < p> tests.py xxx

L'appel à Deconnect doit utiliser les mêmes arguments que le Connect appel ( expéditeur , DisPatch_uid )

Il est nécessaire de connecter à nouveau le signal après le test, sinon il restera déconnecté


0 commentaires

1
votes

Ceci est assez difficile, car comme vous le dites, si vous vous moquez ou que vous importez quelque chose dans le fichier, vous incluez le récepteur dans, vous le connectez automatiquement. Ceci est à travers votre EM> Test Test Suite em> et pas seulement dans le fichier de test en question. Voici un extrait que vous pouvez utiliser, mais vous devez être discipliné dans la suite des commentaires concernant l'évité des importations dans le fichier de destinataires.

from django.test import TestCase

class ReceiverConnectionTestCase(TestCase):
    """TestCase that allows asserting that a given receiver is connected
    to a signal.

    Important: this will work correctly providing you:
        1. Do not import or patch anything in the module containing the receiver
           in any django.test.TestCase.
        2. Do not import (except in the context of a method) the module
           containing the receiver in any test module.

    This is because as soon as you import/patch, the receiver will be connected
    by your test and will be connected for the entire test suite run.

    If you want to test the behaviour of the receiver, you may do this
    providing it is a unittest.TestCase, and there is no import from the
    receiver module in that test module.

    Usage:

        # myapp/receivers.py
        from django.dispatch import receiver
        from apples.signals import apple_eaten
        from apples.models import Apple

        @receiver(apple_eaten, sender=Apple)
        def my_receiver(sender, **kwargs):
            pass


        # tests/integration_tests.py
        from apples.signals import apple_eaten
        from apples.models import Apple

        class TestMyReceiverConnection(ReceiverConnectionTestCase):
            def test_connection(self):
                self.assert_receiver_is_connected(
                    'myapp.receivers.my_receiver',
                    signal=apple_eaten, sender=Apple)

    """
    def assert_receiver_is_connected(self, receiver_string, signal, sender):
        receivers = signal._live_receivers(sender)
        receiver_strings = [
            "{}.{}".format(r.__module__, r.__name__) for r in receivers]
        if receiver_string not in receiver_strings:
            raise AssertionError(
                '{} is not connected to signal.'.format(receiver_string))


0 commentaires

0
votes

J'ai également confronté au problème de la vérification que tous les signaux requis sont connectés. Merci pour tous vos commentaires. Comme le résultat est disponible, il est disponible SignalConnectorTestCase basé sur l'introspection (comme il a été proposé par @ Frank-t) et pour les signaux intégrés La solution de problème initial peut être effectuée comme suit: xxx

pour ses propres signaux, vous pouvez simplement appeler Vérifier fonction de votre méthode de test.


0 commentaires