【问题标题】:Test email sending with no controller在没有控制器的情况下测试电子邮件发送
【发布时间】:2015-10-02 08:52:19
【问题描述】:

我的应用程序发送了许多电子邮件。官方文档通过 HTTP 客户端分析器告诉 how to test emails sending

但我显然没有为我发送的每封电子邮件设置一个控制器。

如何测试不是由控制器触发的电子邮件? (我的意思不是来自请求上下文)。


我的具体案例的更多细节

我正在使用侦听器来触发对正在执行“电子邮件路由”的服务的调用
我想在这里做的是触发一些事件并检查发送的内容(电子邮件正文、标题、收件人......)

【问题讨论】:

    标签: unit-testing symfony email swiftmailer


    【解决方案1】:

    great post 之后,我扩展了Swift_MemorySpool

    class CountableMemorySpool extends \Swift_MemorySpool implements \Countable
    {
        public function count()
        {
            return count($this->messages);
        }
    
        public function getMessages()
        {
            return $this->messages;
        }
    }
    

    将其传递给我的服务使用的邮件程序

    class MailServiceTest extends KernelTestCase
    {
        protected $mailService;
        protected $spool;
    // ...
        protected function setUp()
        {
            $this->spool = new CountableMemorySpool();
            $transport = new \Swift_Transport_SpoolTransport(
                new \Swift_Events_SimpleEventDispatcher(),
                $this->spool
            );
            $mailer = new \Swift_Mailer($transport);
            $this->mailService->setMailer($mailer);
        }
    

    经过测试

        // ...
        public function testMailSpec()
        {
            // ... Sending the mail ...
            $this->assertCount(1, $this->spool,
                'Expected exactly one email to be sent');
            $msg = $this->spool->getMessages()[0];
            $this->assertArrayHasKey('tartempion@test.com', $msg->getTo(),
                'Wrong recipient');
            $this->assertContains('Tartempion', $msg->getBody(),
                'Expected some string contained in the email body');
        }
    }
    

    【讨论】:

      【解决方案2】:

      首先,您链接的文章是关于功能 (e2e) 测试,而不是单元。

      其次,对于单元测试,您需要在 Listener(发送电子邮件)中注入一些 MailerMocker,而不是真正的 Mailer。

      例如,你可以像这样创建一个简单的 Mocker

      class SwiftMailerTester extends \Swift_Mailer
      {
      
          /**
           * @var array[\Swift_Mime_Message]
           *
           */
      
          protected $sentMessages = array ();
      
          /**
           * @var \Swift_Mime_Message
           */
      
          protected $lastSentMessage;
      
          public function __construct() {
      
          }
          /**
           * Mocks sending message
           *
           * @param \Swift_Mime_Message $message
           * @param null                $failedRecepients
           *
           * @return int
           */
          public function send(\Swift_Mime_Message $message, &$failedRecepients = null)
          {
      
              $this->lastSentMessage = $message;
              $this->sentMessages[] = $message;
      
              return 1;
          }
      
          /**
           * @return array[\Swift_Mime_Message]
           */
          public function getSentMessages()
          {
              return $this->sentMessages;
          }
      
          /**
           * @return \Swift_Mime_Message
           */
      
          public function getLastSentMessage()
          {
              return $this->lastSentMessage;
          }
      
          /**
           * @return int
           */
          public function getSentMessagesCount()
          {
              return count($this->sentMessages);
          }
      }
      

      然后在您的单元测试中访问 lastSentMessage(或 sentMessages)来分析 Listener 是否正确地完成了它的工作。

      【讨论】:

      • 谢谢,这很有趣。我实际上正在研究一种基于内存假脱机扩展的技术,我将在这里作为答案。
      【解决方案3】:

      您可能需要考虑设置 global request context,尽管文档是针对命令的,但它应该有助于您的情况,除非您可以提供更多、具体的信息。

      【讨论】:

      • 谢谢。我已经添加了有关我的具体案例的详细信息。我想避免任何请求上下文,因为我的电子邮件 95% 没有发送。
      猜你喜欢
      • 2011-06-06
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 1970-01-01
      • 2014-11-04
      相关资源
      最近更新 更多