代码之家  ›  专栏  ›  技术社区  ›  Dimitrios Desyllas

在不需要调用控制器方法的情况下测试电子邮件发送功能

  •  0
  • Dimitrios Desyllas  · 技术社区  · 7 年前

    当我回头看的时候 this 在symfony的文档中,我意识到实际的测试是在控制器上完成的。

    在我的例子中,我要测试的是服务中的自定义函数,例如:

    class MyMailService
    {
    
     public function __construct(SwiftMailer $mailer)
     {
       $this->mailer=$mailer;
     }
    
    
     public function sendHelloEmail($from,$to)
     {
       $message = (new \Swift_Message('Hello Email'))
            ->setFrom($from)
            ->setTo($to)
            ->setBody('I can see stars');
    
        $this->mailer->send($message);
     }
    
    }
    

    2 回复  |  直到 7 年前
        1
  •  0
  •   Dimitrios Desyllas    6 年前

    正如@BentCoder建议的那样,您可以使用将邮件存储在spool目录中的方法,并检查邮件是否存在。为了识别使用自定义头。在我的例子中,我只是在 X-Agent 头球。

    我的发送电子邮件服务代码是:

    namespace AppBundle\Services;
    
    use AppBundle\Interfaces\EmailSenderInterface;
    use \Swift_Mailer;
    use \Swift_Message;
    
    class NormalEmailSend implements EmailSenderInterface
    {
    
      /**
      * @var Swift_Mailer
      */
      private $mailer=null;
    
      public function __construct(Swift_Mailer $mailer)
      {
        $this->mailer=$mailer;
      }
    
      /**
      * @inheritdoc
      */
      public function send($from,$to,$title="",$bodyPlain="",$bodyHtml="",array $cc=[],array $bcc=[])
      {
    
        $message=new Swift_Message($title);
        $message->setFrom($from)->setTo($to)->setBody($bodyPlain,'text/plain');
    
        if($bodyHtml){
            $message->addPart($bodyHtml,'text/html');
        }
    
        $headers = $message->getHeaders();
        $headers->addTextHeader('X-Agent','ellakcy_member_app');
    
        return $this->mailer->send($message);
      }
    
    
    }
    

    测试是:

    namespace Tests\AppBundle\Services;
    
    use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
    use \Swift_Message;
    use Symfony\Component\Filesystem\Filesystem;
    use Symfony\Component\Finder\Finder;
    use Symfony\Component\HttpKernel\KernelInterface;
    
    use AppBundle\Services\NormalEmailSend;
    
    /**
    * @testype functional
    */
    class ContactEmailSendTest extends KernelTestCase
    {
    
       /**
       * @var AppBundle\Services\NormalEmailSend
       */
       private $service;
    
       /**
       * @var String
       */
       private $spoolPath=null;
    
        /**
        * {@inheritDoc}
        */
         protected function setUp()
         {
             $kernel = self::bootKernel();
             $container = $kernel->getContainer();
             $this->service = $container->get(NormalEmailSend::class);
             $this->spoolPath = $container->getParameter('swiftmailer.spool.default.file.path');
         }
    
        public function testSendEmail()
        {
           $from='sender@example.com';
           $to='receiver@example.com';
           $this->service->send($from,$to,'Hello','Hello','Hello');
           $this->checkEmail();
        }
    
        private function checkEmail()
        {
          $spoolDir = $this->getSpoolDir();
          $filesystem = new Filesystem();
    
          if ($filesystem->exists($spoolDir)) {
              $finder = new Finder();
              $finder->in($spoolDir)
                     ->ignoreDotFiles(true)
                    ->files();
    
              if(!$finder->hasResults()){
                $this->fail('No email has been sent');
              }
    
              $counter=0;
              foreach ($finder as $file) {
                  /** @var Swift_Message $message */
                  $message = unserialize(file_get_contents($file));
                  $header = $message->getHeaders()->get('X-Agent');
                  $this->assertEquals($header->getValue(),'ellakcy_member_app');
                  $counter++;
              }
    
              //@todo Possibly Consinder not doing this check
              if($counter===0){
                  $this->fail('No email has been sent');
              }
    
          } else {
            $this->fail('On test environment the emails should be spooled and not actuallt be sent');
          }
        }
    
    
        /**
        * {@inheritDoc}
        */
        public function tearDown()
        {
            $spoolDir = $this->getSpoolDir();
            $filesystem = new Filesystem();
            $filesystem->remove($spoolDir);
        }
    
        /**
        * @return string
        */
        private function getSpoolDir()
        {
          return $this->spoolPath;
        }
    
    }
    

    希望它有帮助,也可以修改上面看到的代码,以便通过 X-Mail-Id 并将其作为可选参数放在函数的发送参数上,如果数字不为空,则可以将其设置为头。

    因此,当你遍历spool目录时,你可以标记将通过其跟踪号发送的电子邮件。

        2
  •  -1
  •   adsc    7 年前

    没必要那么做。测试邮件是否发送属于功能性甚至系统集成测试的范畴(因为邮件是否实际发送还取决于邮件环境配置、网络等)。如果您只想检查邮件的结构是否正确,那么如果您将实际的邮件创建与邮件发送分开,则可以对服务进行单元测试。