测试电子邮件发送功能,而无需调用控制器方法

时间:2018-08-18 20:27:04

标签: symfony testing swiftmailer symfony-3.4

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

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

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 个答案:

答案 0 :(得分:0)

按照@BentCoder的建议,您可以使用将邮件存储在假脱机目录中的方法,并检查消息是否存在。为了识别使用自定义标题。就我而言,我只是在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放置一个跟踪号,并将其作为可选参数放置在函数的发送参数上,以防万一该数字不为null时,您可以将其设置为标题。

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

答案 1 :(得分:-1)

  

那么我如何能够测试应用程序是否发送电子邮件而无需调用客户端测试?

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