Symfony 测试电子邮件发送功能,无需调用控制器方法
当我查看symfony的文档时,我意识到实际的测试是在一个控制器上进行的 在我的例子中,我要测试的是服务中的自定义函数,例如:Symfony 测试电子邮件发送功能,无需调用控制器方法,symfony,testing,swiftmailer,symfony-3.4,Symfony,Testing,Swiftmailer,Symfony 3.4,当我查看symfony的文档时,我意识到实际的测试是在一个控制器上进行的 在我的例子中,我要测试的是服务中的自定义函数,例如: class MyMailService { public function __construct(SwiftMailer $mailer) { $this->mailer=$mailer; } public function sendHelloEmail($from,$to) { $message = (new \Swift_Mess
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);
}
}
那么,我如何测试应用程序是否发送电子邮件而不需要调用客户端测试呢
那么,我如何测试应用程序是否发送电子邮件而不需要调用客户端测试呢
没有必要这样做。测试是否发送邮件属于功能测试甚至系统集成测试的范畴(因为邮件是否实际发送还取决于邮件环境配置、网络等)。如果您只想检查邮件的结构是否正确,如果您将实际邮件创建与邮件发送分开,则可以对服务进行单元测试。正如@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目录时,您可以标记将通过其跟踪号发送的电子邮件。配置
config
文件test
环境,首先将电子邮件存储在spool
目录中,然后检查电子邮件是否实际位于spool
目录中。整个示例可以在这里找到(通过检查behat中的spool目录来测试电子邮件)。您所要做的就是从FeatureContext
文件中提取代码。这应该很容易!您始终可以创建Symfony命令来调用您的服务的“sendHelloEmail()
方法。我刚刚意识到,我上面的评论中缺少URL。这也是我想要做的,我可以在一些测试用例中检查这个函数是否工作,这样我就可以轻松地模拟它,然后进行实际的单元测试。我首先需要创建一个更具可模拟性的实体,并使用功能测试和集成测试对其进行测试,这样我就可以通过单元测试测试其余的代码。