[英]Why does Django's send_mail not work during testing?
我有一個應用程序可以導入多個用戶電子郵件地址並為它們創建帳戶。 為了讓他們設置自己的密碼,我嘗試使用 django 的 PasswordResetForm(在 django.contrib.auth.forms 中)。 創建用戶帳戶后立即調用密碼重置:
def reset_password(person):
form = PasswordResetForm({'email': person.email})
if form.is_valid():
form.save(from_email='myname@myserver.com')
除了包含執行此操作的單元測試之外,我還沒有進一步進行測試:
import password_reset_module
class TestPasswordReset(TestCase):
def setUp(self):
p = Person(email='test@test.com')
def test_send(self):
password_reset_module.reset_password(p)
沒有斷言,現在我只想通過監視我運行的控制台來查看是否有郵件發送:
python -m smtpd -n -c DebuggingServer localhost:1025
保存表單調用 django 的 send_mail。 運行測試用例時,send_mail 方法返回 1。但是,控制台中沒有顯示任何郵件。 奇怪的是從django的交互式shell調用send_mail:
python manage.py shell
工作正常。 郵件顯示在控制台中。 在瀏覽器中單擊忘記密碼鏈接也會導致發送郵件。
我也試過基於文件的電子郵件后端無濟於事。 當前 settings.py 電子郵件設置:
EMAIL_USE_TLS = False
EMAIL_HOST = 'localhost'
DEFAULT_FROM_EMAIL = 'myname@myserver.com'
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_PORT = 1025
現在想知道我在調用密碼重置時是否遺漏了什么,或者手頭是否存在郵件服務器配置問題?
在“電子郵件服務”部分, Django 測試文檔說:
Django 的測試運行器會自動將所有 Django 發送的電子郵件重定向到一個虛擬發件箱。 [...] 在測試運行期間,每封外發電子郵件都保存在
django.core.mail.outbox
。 這是已發送的所有EmailMessage
實例的簡單列表。
嗯?
Django 測試運行器實際上會為您配置一個不同的電子郵件后端(稱為locmem )。 如果您只想進行單元測試(不與實際的電子郵件服務器集成),這非常方便,但如果您不知道,則非常令人驚訝。
(我沒有使用 Django 測試運行程序manage.py test
,但它無論如何都會發生,大概是因為我安裝了pytest-django
,它神奇地修改了我的py.test
。)
如果您想覆蓋覆蓋並使用settings
模塊中給出的電子郵件配置,您需要重新設置的是電子郵件后端的設置,例如:
@django.test.utils.override_settings(
EMAIL_BACKEND='django.core.mail.backends.smtp.EmailBackend')
def test_send_email_with_real_SMTP(self):
...
嘗試將其轉換為適當的單元測試可能是值得的,然后您當然可以將其作為自動化測試套件的一部分運行。 對於單元測試,檢查郵件是否已發送(並在需要時驗證郵件內容)的最簡單方法可能是使用 Django 的內置內存電子郵件后端 - 您可以簡單地使用 outbox 屬性來獲取已發送郵件列表:
https://docs.djangoproject.com/en/dev/topics/email/#in-memory-backend
這樣做的優點是不需要任何基礎設施設置來支持測試電子郵件發送,使得斷言電子郵件的內容變得非常簡單,並且這也應該使測試快速(與實際將電子郵件發送到 SMTP 服務器相比)。
希望這可以幫助。
據我了解,您在測試單元時正在運行以下命令。
python -m smtpd -n -c DebuggingServer localhost:1025
此命令啟動一個“啞” SMTP 服務器,該服務器接收您的電子郵件並將其顯示在終端上。 嘗試在沒有設置此 DebuggingServer 的情況下運行您的站點,並查看郵件是否已發送。
這是對文檔頁面的參考
您可以使用 pytest-django 的mailoutbox固定裝置:
一個干凈的電子郵件發件箱,Django 生成的電子郵件將發送到該發件箱。
例子
from django.core import mail
def test_mail(mailoutbox):
mail.send_mail('subject', 'body', 'from@example.com', ['to@example.com'])
assert len(mailoutbox) == 1
m = mailoutbox[0]
assert m.subject == 'subject'
assert m.body == 'body'
assert m.from_email == 'from@example.com'
assert list(m.to) == ['to@example.com']
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.