You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Django-RQ Worker发送测试邮件未进入mail.outbox问题咨询

Django-RQ后台发送邮件测试:mail.outbox捕获不到邮件的解决办法

问题原因

是的,你猜的没错——Django-RQ的worker是在独立子进程中执行任务的。Django测试用的mail.outbox是当前测试进程的内存实例,两个进程的内存空间完全隔离,所以worker进程发送的邮件根本不会进入测试进程的mail.outbox,这就是控制台显示任务成功但断言失败的核心原因。

解决方法

这里提供三种实用方案,按需选择:

1. 测试环境强制同步执行RQ任务

直接让RQ任务在当前测试进程中同步执行,不需要启动worker,邮件自然会进入mail.outbox。可以通过两种方式实现:

全局测试配置

在test_settings.py中添加全局配置:

# 测试环境下禁用RQ异步执行
RQ_ASYNC = False

单个测试用例临时修改

如果只想针对当前测试用例生效,可在测试方法中临时切换配置:

from django.conf import settings

def test_reset_password(self):
    # 保存原配置,临时开启同步模式
    original_rq_async = settings.RQ_ASYNC
    settings.RQ_ASYNC = False

    c = Client()
    page = reverse_lazy("accounts:password_reset")
    response = c.post(page, {'email': 'joe@test.co.uk'})
    self.assertRedirects(response, reverse_lazy("accounts:login"), 302, 200)

    # 无需启动worker,任务已同步执行
    self.assertEqual(len(mail.outbox), 1)
    self.assertEqual(mail.outbox[0].subject, 'Password reset instructions')

    # 恢复原配置
    settings.RQ_ASYNC = original_rq_async

2. 拆分测试逻辑:分别验证入队和邮件发送

把测试拆成两部分,既验证请求是否正确将任务加入队列,又单独测试任务函数的邮件发送逻辑,更贴近真实业务流程:

from unittest.mock import patch
from django_rq import get_queue
# 假设你的邮件任务函数是send_reset_email
from accounts.tasks import send_reset_email

def test_reset_password(self):
    c = Client()
    page = reverse_lazy("accounts:password_reset")
    
    # 第一步:验证任务是否被正确加入队列
    with patch.object(get_queue(settings.RQ_QUEUE), 'enqueue') as mock_enqueue:
        response = c.post(page, {'email': 'joe@test.co.uk'})
        self.assertRedirects(response, reverse_lazy("accounts:login"), 302, 200)
        # 断言任务入队的参数正确
        mock_enqueue.assert_called_once_with(send_reset_email, 'joe@test.co.uk')
    
    # 第二步:单独测试任务函数的邮件发送逻辑
    send_reset_email('joe@test.co.uk')
    self.assertEqual(len(mail.outbox), 1)
    self.assertEqual(mail.outbox[0].subject, 'Password reset instructions')

3. 使用共享邮件后端(进阶)

如果一定要模拟真实多进程场景,可以改用非内存的邮件后端(比如数据库后端),让不同进程的邮件发送记录统一存储。不过这种方式配置复杂,仅适用于需要验证多进程邮件逻辑的特殊测试场景,一般测试不需要。

总结

日常测试优先选择前两种方案:

  • 快速验证选方案1,简单直接,无需额外修改业务逻辑;
  • 追求测试严谨性选方案2,覆盖任务入队和邮件发送两个核心环节,测试粒度更细。

内容的提问来源于stack exchange,提问作者Scratcha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 12:35:31