102

Django アプリケーションが正しい内容の電子メールを送信することをテストする必要があります。実際の電子メール サービスをテストしていないため、外部システム (アドホックのGmailアカウントなど) に依存したくありません...

おそらく、電子メールを送信時にフォルダー内にローカルに保存したいと思います。それを達成する方法に関するヒントはありますか?

4

10 に答える 10

200

Django テスト フレームワークには、電子メール サービスのテストを支援するヘルパーが組み込まれています。

ドキュメントからの例 (短いバージョン):

from django.core import mail
from django.test import TestCase

class EmailTest(TestCase):
    def test_send_email(self):
        mail.send_mail('Subject here', 'Here is the message.',
            'from@example.com', ['to@example.com'],
            fail_silently=False)
        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].subject, 'Subject here')
于 2010-09-16T16:18:09.447 に答える
47

電子メールの送信にファイル バックエンドを使用できます。これは、開発とテストにとって非常に便利なソリューションです。メールは送信せず、指定できるフォルダに保存!

于 2010-09-16T16:10:54.013 に答える
25

単体テストを行う場合、最善の解決策は、django が提供するインメモリ バックエンドを使用することです。

EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'

py.testフィクスチャとして使用する場合を考えてみましょう

@pytest.fixture(autouse=True)
def email_backend_setup(self, settings):
    settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'  

各テストではmail.outbox、サーバーで がリセットされるため、テスト間の副作用はありません。

from django.core import mail

def test_send(self):
    mail.send_mail('subject', 'body.', 'from@example.com', ['to@example.com'])
    assert len(mail.outbox) == 1

def test_send_again(self):
    mail.send_mail('subject', 'body.', 'from@example.com', ['to@example.com'])
    assert len(mail.outbox) == 1
于 2016-04-25T17:33:56.183 に答える
10

MailHogを使用する

MailCatcher にインスパイアされ、簡単にインストールできます。

Go で構築 - MailHog は複数のプラットフォームでインストールせずに実行されます。


また、 Jimと呼ばれるコンポーネント、MailHog Chaos Monkeyがあり、さまざまな問題が発生している電子メールの送信をテストできます。

ジムは何ができますか?

  • 接続を拒否する
  • レート制限接続
  • 認証を拒否する
  • 送信者を拒否
  • 受信者を拒否

詳しくはこちらをご覧ください。


( UTF-8 でエンコードされた絵文字を含むメールを送信するときに失敗した元の mailcatcher とは異なり、現在のリリースでは実際には修正されていませんが、MailHog は機能します。)

于 2016-08-26T13:21:17.673 に答える
5

添付ファイルの送信を必要としないプロジェクトでは、django-mailerを使用します。これには、送信をトリガーするまですべての送信メールがキューに入れられるという利点があり、送信された後でもログに記録されます-これらはすべて管理画面に表示されるため、メール送信コードがインターチューブに送信しようとしているものをすばやく簡単に確認できます。

于 2010-09-16T16:17:46.033 に答える
4

Django には、メモリ内メール バックエンドもあります。詳しくは、インメモリ バックエンドのドキュメントを参照してください。これは Django 1.6 に存在しますが、それ以前に存在するかどうかはわかりません。

于 2014-06-26T18:29:52.187 に答える
2

テスト目的で SMTPLib にパッチを適用すると、メールを送信せずに送信をテストするのに役立ちます。

于 2010-09-16T16:15:03.643 に答える
1

inherit fromsmtpd.SMTPServerと を使用して、独自の非常に単純な SMTP サーバーを起動してみませんかthreading.Thread

class TestingSMTPServer(smtpd.SMTPServer, threading.Thread):
    def __init__(self, port=25):
        smtpd.SMTPServer.__init__(
            self,
            ('localhost', port),
            ('localhost', port),
            decode_data=False
        )
        threading.Thread.__init__(self)

    def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
        self.received_peer = peer
        self.received_mailfrom = mailfrom
        self.received_rcpttos = rcpttos
        self.received_data = data

    def run(self):
        asyncore.loop()

process_message は、SMTP サーバーがメール リクエストを受信するたびに呼び出されます。ここでは、好きなことを行うことができます。

テスト コードで、次のようにします。

smtp_server = TestingSMTPServer()
smtp_server.start()
do_thing_that_would_send_a_mail()
smtp_server.close()
self.assertIn(b'hello', smtp_server.received_data)

asyncore ループを終了するために呼び出すことを忘れないでください (サーバーのリッスンを停止しclose()ますasyncore.dispatcher) 。smtp_server.close()

于 2016-09-18T13:54:18.503 に答える