そのため、アプリ間で送信されるさまざまなシグナルとハンドラーがあります。ただし、テストを実行するとき/「テストモード」に入るときは、これらのハンドラーを無効にします。
テストモードでシグナル/ハンドラーを無効にするDjango固有の方法はありますか?非常に簡単な方法(if TESTING句内にハンドラーを含める)を考えることができますが、Djangoに組み込まれているより良い方法があるかどうか疑問に思っていました...
いいえ、ありません。ただし、条件付き接続は簡単に作成できます。
import sys
if not 'test' in sys.argv:
signal.connect(listener, sender=FooModel)
一連のテストケースのシグナルを無効にすることを検討しているときにこの質問を見つけました。ゲルマノの答えは私を解決策に導きましたが、それは反対のアプローチを取るので、私はそれを追加すると思いました。
テストクラスの場合:
class MyTest(TestCase):
def setUp(self):
# do some setup
signal.disconnect(listener, sender=FooModel)
シグナルを追加するために決定コードを追加する代わりに、テストの時点でそれを無効にしました。これは、私にとってより良い解決策のように感じます(テストは、テストの周りのコードではなく、コードの周りに書く必要があるため)。うまくいけば、同じボートの誰かに役立つでしょう!
編集:これを書いているので、私はテストのために信号を無効にする別の方法を紹介されました。これには factory_boy パッケージ(v2.4.0 +)が必要です。これは、Djangoでのテストを簡素化するのに非常に便利です。あなたは本当に選択のために甘やかされています:
import factory
from Django.db.models import signals
class MyTest(TestCase):
@factory.Django.mute_signals(signals.pre_save, signals.post_save)
def test_something(self):
Upsのおかげで警告:ファクトリ内およびオブジェクトの作成時にシグナルをミュートしますが、明示的なsave()を作成する場合はテスト内でそれ以上ミュートしません-シグナルはそこでミュート解除されます。これが問題である場合は、setUpで単純な切断を使用するのがおそらく最善の方法です。
FactoryBoyを使用したくない場合に、テストで特定のシグナルを無効にする方法をインポートした完全な例を次に示します。
from Django.db.models import signals
from myapp.models import MyModel
class MyTest(TestCase):
def test_no_signal(self):
signals.post_save.disconnect(sender=MyModel, dispatch_uid="my_id")
... after this point, the signal is disabled ...
これはレシーバーと一致する必要があります。この例はこのレシーバーと一致します。
@receiver(post_save, sender=MyModel, dispatch_uid="my_id")
dispatch_uidを指定せずにシグナルを無効にしようとしましたが、機能しませんでした。
同様の問題が発生し、signals.post_save.disconnect()
を使用してシグナルを正常に切断できませんでした。見つかりました this 指定されたテストとシグナルの_SUSPEND_SIGNALS
_設定をオーバーライドするデコレータを作成する代替アプローチ。同じボートに乗っている人なら誰にでも役立つかもしれません。
まず、デコレータを作成します。
_import functools
from Django.conf import settings
from Django.dispatch import receiver
def suspendingreceiver(signal, **decorator_kwargs):
def our_wrapper(func):
@receiver(signal, **decorator_kwargs)
@functools.wraps(func)
def fake_receiver(sender, **kwargs):
if settings.SUSPEND_SIGNALS:
return
return func(sender, **kwargs)
return fake_receiver
return our_wrapper
_
シグナルの通常の_@receiver
_デコレータを新しいものに置き換えます。
_@suspendingreceiver(post_save, sender=MyModel)
def mymodel_post_save(sender, **kwargs):
work()
_
TestCaseでDjangoの override_settings()
を使用します。
_@override_settings(SUSPEND_SIGNALS=True)
class MyTestCase(TestCase):
def test_method(self):
Model.objects.create() # post_save_receiver won't execute
_
ブログを書いたJoshSmeatonに感謝します。
ドキュメントで推奨されているAppConfig.ready
の信号にレシーバーを接続する場合は、 https://docs.djangoproject.com/en/2.2/topics/signals/#connecting-receiver-functions を参照してください。 =、他の信号受信機でのテスト用に代替のAppConfig
を作成できます。