Symfonyã®DIãå©ç¨ãã¦Mailéä¿¡ã¯ã©ã¹ãã¤ã³ãã°ã¬ã¼ã·ã§ã³ãã¹ãããï¼ã³ã¼ãç·¨
ã追è¨ã
æ°ããæ¸ãããã¡ãã®è¨äºãåèã«ããã»ããè¯ãã§ãã Symfonyでメールのインテグレーションテストを行う - プログラミング - THIS IS IT !
追è¨çµãã
ãã®è¨äºã¯Symfony Advent Calender 2014 8æ¥ç®ã®è¨äºã«ãªãã¾ãã
- å(12æ7æ¥)ï¼StofDoctrineExtensionsBundle ã«ã¤ãã¦ä½¿ã£ãã調ã¹ã¦ã¿ã
- å¾(12æ9æ¥) monologã§PHPã®Fatalã¨ã©ã¼ããã°ã«æ®ã
æ¨æ¥ã¯ ohsawa0515ããã®ãStofDoctrineExtensionsBundle ã«ã¤ãã¦ä½¿ã£ãã調ã¹ã¦ã¿ããã§ããã
ä»å¹´ã®Symfony Advent Calender 2014ã¯çãä¸ãã£ã¦ã¾ãããæ¢ã«å ¨æ åã¾ã£ã¦ãã¾ãã 䏿¨å¹´ãæ ãåã¾ããä½å¨ãè¨äºãæ¸ãã¦ãæ¹ãããããããã£ããã£ãäºãèããã¨æåãã®ã§ãï¼ç¬ï¼
追è¨
ãã®è¨äºã®å 容ããæ°ããæ¸ãã以ä¸ã®è¨äºãåèã«ãããã¨ããããããã¾ãã
追è¨çµãã
ãã¦æ¬é¡
Symfonyã®DIãå©ç¨ãã¦Mailéä¿¡ã¯ã©ã¹ãã¤ã³ãã°ã¬ã¼ã·ã§ã³ãã¹ããã
åç½®ã
æ¸ãã¦ããããã¾ãã«è¶ 大ä½ã«ãªã£ã¦ãã¾ã£ãã®ã§åç·¨ãä½ãã¾ãããèå³ãããæ¹ã¯èªãã§ã¿ã¦ãã ããã
SymfonyDIを利用してMail送信クラスをインテグレーションテストする:前置き編 - プログラミング - THIS IS IT !
æ¬ç¨¿ã§åãä¸ããå 容
ãµã³ãã«ã³ã¼ã
ãµã³ãã«ã³ã¼ãã¯githubã«ã¢ãããã¦ãã¾ãã
GitHub - okapon/mail-test-sample: Symfony2でメール送信クラスをテストするコードサンプル
以ä¸ã®ç°å¢ã§åä½ç¢ºèªããã¦ãã¾ãã
Symfony 2.6.1 php 5.5.18 phpunit 3.7.38
github ãããã§ãã¯ã¢ã¦ããã¦ä¸è¨ã³ãã³ããå®è¡ãããã¨ã§ãã¹ããå®è¡ã§ãã¾ãã ã¨ãã£ã¦ãå®è¡ããããã¹ãã¯1ã¤ã ãã§ããã
$ composer install $ ./vendor/phpunit/phpunit/phpunit.php -c app
ã³ã¼ãã®è§£èª¬
ãããã¯ãã³ã¼ã
ã¾ããããã¯ãã³ã¼ãã§ãããSymfonyã®å
¬å¼ããã¥ã¡ã³ãããµã¼ãã¹ã³ã³ãããã®ç« ã§ãNewsletterManager
ãµã¼ãã¹ã®ä½ãæ¹ãç´¹ä»ããã¦ããã®ã§ãããã«ç¿ã£ã¦MailService
ä½ã£ã¦ããæ¹ãå¤ãã®ã§ã¯ãªãã§ããããã
ããã¨ä¼¼ãã³ã¼ãã§ãããä»åã¯ä»¥ä¸ã®ãããªãããã¯ãã³ã¼ããèãã¦ã¿ã¾ããã¦ã¼ã¶ã¼ç»é²ãè¡ã£ãéã«éä¿¡ããããã¡ã¼ã«ã®æã¡ä¸»ç¢ºèªãè¡ãã¢ã¯ãã£ãã¼ã·ã§ã³ã¡ã¼ã«ãéããã®ãæ³å®ãã¦ã¾ãã
<?php namespace AppBundle\Service; use AppBundle\Entity\User; class MailService { protected $mailer; protected $twig; /** * Constructor * * @param \Swift_Mailer $mailer * @param \Twig_Environment $twig */ public function __construct(\Swift_Mailer $mailer, \Twig_Environment $twig) { $this->mailer = $mailer; $this->twig = $twig; } public function sendRegistrationMail(User $user) { // èªè¨¼URLã使ãããããã§ã¯ãµã³ãã«ã³ã¼ããªã®ã§åºå®ã§è¨è¿°ãã¦ãã¾ã $activationUrl = 'http://example.com/activation?code=abcdefg'; $body = $this->render('AppBundle:Mail:register.txt.twig', [ 'user' => $user, 'activationUrl' => $activationUrl, ]); $subject = '[xxx ãµã¼ãã¹] ãç»é²ãããã¨ããããã¾ã'; $fromEmail = '[email protected]'; $userEmail = $user->getEmail(); $message = \Swift_Message::newInstance() ->setFrom($fromEmail) ->setTo($userEmail) ->setSubject($subject) ->setBody($body) ; return $this->sendMessage($message); } /** * sendMessage * * @param \Swift_Message $message * @return void */ protected function sendMessage(\Swift_Message $message) { $this->mailer->send($message); } /** * render * * @param string $template * @param array $vars * @return string */ protected function render($template, array $vars = []) { return $this->twig->loadTemplate($template)->render($vars); } }
ãã®ã³ã¼ãã«å¯¾ãããã¹ãã³ã¼ããæ¸ãã¦ãããã¨æãã¾ãããããã§åé¡ã¨ãªãã®ãtestã¢ã¼ãã§ãã¹ããå®è¡ããå ´åã«ã¯SwiftMailerã¯ãããã©ã«ãã§ã¯ã¡ã¼ã«éä¿¡å¦çãè¡ãã¾ããã
ãã¨ãã£ã¦ãã¹ãã³ã¼ããå®è¡ãããã³ã«å¤é¨ã«ã¡ã¼ã«ãéä¿¡ãã¦ãã¾ãã®ã¯ãã使³ã¨ã¯ããã¾ã¾ããã å®éã«ã¡ã¼ã«éä¿¡ã¯è¡ãããã¯ãªããããã©ãã¡ã¼ã«ã®ç¢ºèªã¯ãããã
ãã®åé¡ã解決ããããã®ãã³ãã¯Symfonyã®ããã¥ã¡ã³ãã«ããã¾ãã
è±èªã®ããã¥ã¡ã³ãã§ã¾ã æ¥æ¬èªã«ç¿»è¨³ããã¦ãã¾ãããããã¡ã³ã¯ã·ã§ãã«ãã¹ãä¸ã§ã¡ã¼ã«éä¿¡ã確èªããæ¹æ³ãç´¹ä»ããã¦ãã¾ãã
How to Test that an Email is Sent in a functional Test(è±èª)
How to Test that an Email is Sent in a Functional Test (Symfony Docs)
ãããã¡ã¼ã«ã®ãã¹ããããããã«ã$client = static::createClient();
ãã¦ãã³ã³ããã¼ã©ã¼ã®ãã¹ãã¾ã§ããªãã¨ãããªãã¨ããã®ã¯å°ãé¢åã§ãã
ããã§ä»åã®è¨äºã®æ¬é¡ã§ãããSymfonyDIã使ã£ã¦å°ã工夫ãããã¨ã§ãä¸è¨ã®ãããªã¡ã¼ã«ã®ãã¹ããè¡ãæ¹æ³ãç´¹ä»ãããã¨æãã¾ãã
ãã¹ãã³ã¼ã
1 ãã©ã¡ã¼ã¿ã¼ã使ã£ã¦MailService
ã¯ã©ã¹ãæå®ããããã«ãã¾ãã
â»ãµã¼ãã¹ã³ã³ããã®ã³ã³ãã£ã®ã¥ã¬ã¼ã·ã§ã³ã¯ymlã§è¨è¿°ãããã®ã¨ãã¾ãã
service.yml
parameters: app.mail_service.class: AppBundle\Service\MailService services: app.mail_service: class: %app.mail_service.class% arguments: - @mailer - @twig
2 ãã¹ãã³ã¼ãã ãã§èªã¿è¾¼ã¾ããservice_test.ymlãç¨æãã¦ãä¸è¨ã®MailService
ãç½®ãæãã
service_test.yml
parameters: app.mail_service.class: AppBundle\Tests\Mock\Service\TestMailService
3 service_test.yml
ãèªã¿è¾¼ã
<?php namespace AppBundle\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; /** * This is the class that loads and manages your bundle configuration * * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html} */ class AppExtension extends Extension { /** * {@inheritdoc} */ public function load(array $configs, ContainerBuilder $container) { $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('services.yml'); // testç°å¢ã ããã¡ã¤ã«ãèªã¿è¾¼ã $env = $container->getParameter("kernel.environment"); if ($env === 'test') { $loader->load('services_test.yml'); } } }
4 ç½®ãæããã¯ã©ã¹ã§ã¡ã¼ã«ã®ç¢ºèªãã§ããããã«æ¡å¼µãã
<?php namespace AppBundle\Tests\Mock\Service; use AppBundle\Service\MailService; /** * TestMailService. * * éä¿¡ã¡ã¼ã«ã®å 容ããã¹ããããããSwift_Messageãå é¨ã«ä¿æã * å¾ããåãã ãããã¨ãã§ããããã«ãããã¹ãç¨ã®ã¯ã©ã¹ * */ class TestMailService extends MailService { /** * @var Swift_Message[] */ protected $messages = []; /** * {@inheritDoc} */ public function sendMessage(\Swift_Message $message) { $this->messages[] = $message; // ããããã¤ã³ã return parent::sendMessage($message); } /** * @return Swift_Message[] */ public function getMessages() { return $this->messages; } }
ãã¤ã³ãã¯sendMessage()
ããªã¼ãã¼ã©ã¤ããã¦ã¯ã©ã¹ã®å
é¨å¤æ°ã«Swift_message
ã¤ã³ã¹ã¿ã³ã¹ãä¿æãã¦ãããã¨ã§ãã
ã¾ãããã®ã¤ã³ã¹ã¿ã³ã¹ãåå¾ã§ããããgetMessagesã§åå¾ãã¦ã¾ãã
ãã¹ãã³ã¼ãã¯ä»¥ä¸ã®ããã«ãªãã¾ããã
<?php namespace AppBundle\Service; use Phake; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use AppBundle\Entity\User; class MailServiceIntegrationTest extends WebTestCase { protected $mailService; public function setUp() { $kernel = self::createKernel(); $kernel->boot(); $container = $kernel->getContainer(); $this->mailService = $container->get('app.mail_service'); } /** * @test */ public function sendRegistrationMail() { $fromEmail = '[email protected]'; $userEmail = '[email protected]'; $userName = 'ç°ä¸ 太é'; $activationUrl = 'http://example.com/activation?code=abcdefg'; $user = Phake::mock(User::class); Phake::when($user)->getUsername()->thenReturn($userName); Phake::when($user)->getEmail()->thenReturn($userEmail); // test (ã¡ã¼ã«éä¿¡) $this->mailService->sendRegistrationMail($user); // éä¿¡ãããã¡ãã»ã¼ã¸ã®ã¤ã³ã¹ã¿ã³ã¹ãåå¾ $messages = $this->mailService->getMessages(); $this->assertCount(1, $messages); // 1éç®ã ããã¹ã $message = $messages[0]; $this->assertInstanceOf('Swift_Message', $message); $expected = [ 'from' => $fromEmail, 'to' => $userEmail, 'subject' => '[xxx ãµã¼ãã¹] ãç»é²ãããã¨ããããã¾ã', 'body' => [ $userName, $activationUrl, ] ]; $this->verifyMail($message, $expected); } protected function verifyMail(\Swift_Message $message, array $expected) { // From & To ã¢ãã¬ã¹ãæ¤è¨¼ $this->assertEquals($expected['from'], key($message->getFrom())); $this->assertEquals($expected['to'], key($message->getTo())); // Subject $this->assertEquals($expected['subject'], $message->getSubject()); // Body foreach ($expected['body'] as $body) { $this->assertContains($body, $message->getBody()); } } }
$this->message = $container->get('app.mail_service')
ã§åå¾ãããã¤ã³ã¹ã¿ã³ã¹ã¯ãAppBundle\Tests\Mock\Service\TestMailService
ã«ç½®ãæãã£ã¦ãã¾ãã
$messages = $this->mailService->getMessages();
ã§éä¿¡ãããSwift_Message
ã¤ã³ã¹ã¿ã³ã¹ãåãåºãæ³å®éãã®ã¡ãã»ã¼ã¸ã¨ãªã£ã¦ããã確èªãã¾ãã
ããã§ã¯ãFromã¢ãã¬ã¹ãToã¢ãã¬ã¹ãä»¶åã®å®å ¨ä¸è´ãæ¬æã«ãååããã¢ã¯ãã£ãã¼ã·ã§ã³URLããå«ã¾ãã¦ããããæ¤è¨¼ãã¦ãã¾ãã
å ´åã«ãã£ã¦ã¯æ¬æãå ¨æä¸è´ã§æ¤è¨¼ãã¦ãããã§ãããå¿ è¦ãªæ å ±ãåºåããã¦ããã°ããã¨ã®å¤æã§ããæé¢ãããããã¨ãããã¾ããã
æ¬æãå
¨ã¦ç¢ºèªãããå ´åã«ã¯ãå¿
殺ã®var_dump($message->getBody())
ã使ãã¾ãããæçµçã«ãã©ã¦ã¶ãã¹ããå¿
è¦ãªã®ã§ã¾ãå¥ã«ç¢ºèªããããã¾ãã
â» å½ç¶ã®ããã«Phakeãå©ç¨ãã¦ã¾ãããPhakeã¯PHPã®ã¢ããã³ã°ã©ã¤ãã©ãªã§ãã Welcome to Phake - PHP Mocking Framework’s documentation! — Phake - PHP Mocking Framework 1.0.3 documentation
ã¾ã¨ã
- DIã¨ã¯ã©ã¹ã®ãã©ã¡ã¼ã¿ã¼åãå©ç¨ãããã¨ã§ããã¹ã対象ã®ã¯ã©ã¹ã容æã«ç½®ãæãããã¨ãã§ãã¾ããã
- ãã®ããã«ãã¹ããã«ãã対象ã¯ã©ã¹ãç¶æ¿ãã¦ãå é¨ç¶æ ãæ¤æ»ãããããªææ³ã¯ãã¹ãã³ã¼ããæ¸ãæè¡ã¨ãã¦ãã°ãã°å©ç¨ããã¦ãã¾ããï¼å®éSymfony2ã®ãã¹ãã³ã¼ãã§ã¿ããã¾ãï¼
- ã¡ã¼ã«ã®ãã¹ãã§é¢åãªãã©ã¦ã¶æä½ãä½åº¦ãè¡ãå¿ è¦ããªããªãã¾ãï¼â»æä½éã®åä½ç¢ºèªã¯å¿ è¦ã§ãï¼