2015-12-19 2 views
10

私はTwig_Environmentを使ってHTMLメールを送信します。私は他のサービスがそれらのメールを送信するために使用されるNotificationServiceクラスを持っています。私は、スタックトレースデバッグし、問題がサービスクラスのTwig_Environmentは、Symfony 2.8のunittestingのときにのみDIC RuntimeExtensionにつながります。

kernelを注入 file_locator使用しています)Twig_Environmentであるように思わ Symfony\Component\DependencyInjection\Exception\RuntimeException: You have requested a synthetic service ("kernel"). The DIC does not know how to construct this service

:と通常の使用で

、すべてが正常に動作しているが、2.8にアップデートしたので、ユニットテストは失敗します
/** 
* Notification Service Class 
* 
* @DI\Service("app.service.notification") 
*/ 
class NotificationService extends Generic 
{ 
    /** 
    * @var \Twig_Environment 
    */ 
    protected $twig; 

    /** 
    * @var \Swift_Mailer 
    */ 
    protected $swiftMailer; 

    /** 
    * @var string 
    */ 
    protected $mailTemplate = 'VendorAdminBundle:Email:system2.html.twig'; 

    /** 
    * @param \Swift_Mailer  $swiftMailer 
    * @param \Twig_Environment $twig 
    * 
    * @DI\InjectParams({ 
    *  "swiftMailer" = @DI\Inject("mailer"), 
    *  "twig" = @DI\Inject("twig") 
    * }) 
    */ 
    public function __construct(\Swift_Mailer $swiftMailer, \Twig_Environment $twig) 
    { 
     $this->twig   = $twig; 
     $this->swiftMailer = $swiftMailer; 
    } 

    /** 
    * Send notification mail to Manager 
    * @param UserEntity $manager 
    * @param array  $contacts 
    */ 
    public function notifyManager(UserEntity $manager, array $contacts) 
    { 
     $subject = 'Lorem Ipsum'; 
     $templateFile = "AppBundle:Email:notifyManager.html.twig"; 
     $templateContent = $this->twig->loadTemplate($templateFile); 
     $body = $templateContent->render(array(
      'user'  => $manager, 
      'contacts' => $contacts, 
      'subject' => $subject, 
     )); 

     $this->sendMail($body, $subject, $manager); 
    } 
} 

これを解決する方法の指針はありますか?

EDITは:

class NotificationTest extends DoctrineTestCase 
{ 
    /** 
    * @var \App\Service\Notification 
    */ 
    protected $service; 

    public function setUp() 
    { 
     $this->markTestSkipped('Problem with twig env'); 

     $this->loadFixturesFromDirectory(__DIR__ . '/DataFixtures'); 
     $this->loginUser('admin', $this->getUser(1)); 
     $this->service = $this->container->get('neos.service.notification'); // <-- exception thrown here 
    } 

    [test methods] 
} 

(要リクエスト)EDIT2:

/** 
* Class DoctrineTestCase. 
* 
* This is the base class to load doctrine fixtures using the symfony configuration 
*/ 
class DoctrineTestCase extends TestCase 
{ 
    /** 
    * @var \Symfony\Component\DependencyInjection\Container 
    */ 
    protected $container; 

    /** 
    * @var \Doctrine\ORM\EntityManager 
    */ 
    protected $em; 

    /** 
    * @var string 
    */ 
    protected $environment = 'test'; 

    /** 
    * @var bool 
    */ 
    protected $debug = true; 

    /** 
    * @var string 
    */ 
    protected $entityManagerServiceId = 'doctrine.orm.entity_manager'; 

    /** 
    * Constructor. 
    * 
    * @param string|null $name  Test name 
    * @param array  $data  Test data 
    * @param string  $dataName Data name 
    */ 
    public function __construct($name = null, array $data = array(), $dataName = '') 
    { 
     parent::__construct($name, $data, $dataName); 

     if (!static::$kernel) { 
      static::$kernel = self::createKernel(array(
       'environment' => $this->environment, 
       'debug' => $this->debug, 
      )); 
      static::$kernel->boot(); 
      static::$kernel->getContainer()->set('kernel', static::$kernel); //<--- Added - but doesnt help 
     } 

     $this->container = static::$kernel->getContainer(); 
     $this->em = $this->getEntityManager(); 
    } 

    /** 
    * Executes fixtures. 
    * 
    * @param \Doctrine\Common\DataFixtures\Loader $loader 
    */ 
    protected function executeFixtures(Loader $loader) 
    { 
     $purger = new ORMPurger(); 
     $executor = new ORMExecutor($this->em, $purger); 
     $executor->execute($loader->getFixtures()); 
    } 

    /** 
    * Load and execute fixtures from a directory. 
    * 
    * @param string $directory 
    */ 
    protected function loadFixturesFromDirectory($directory) 
    { 
     $loader = new ContainerAwareLoader($this->container); 
     $loader->loadFromDirectory($directory); 
     $this->executeFixtures($loader); 
    } 

    /** 
    * Returns the doctrine orm entity manager. 
    * 
    * @return object 
    */ 
    protected function getEntityManager() 
    { 
     return $this->container->get($this->entityManagerServiceId); 
    } 
} 

EDIT3:カーネルをGeting は、過去に時々変更されているようです。

public function __construct($name = null, array $data = array(), $dataName = '') 
{ 
    parent::__construct($name, $data, $dataName); 

    if (!static::$kernel) { 
     static::$kernel = self::createKernel(array(
      'environment' => $this->environment, 
      'debug' => $this->debug, 
     )); 
     static::$kernel->boot(); 
     static::$kernel->getContainer()->set('kernel', static::$kernel); //<--- Added - but doesnt help 
    } 

    $this->container = static::$kernel->getContainer(); 
    $this->em = $this->getEntityManager(); 
} 

へ:

public function __construct($name = null, array $data = [], $dataName = '') 
{ 
    parent::__construct($name, $data, $dataName); 

    self::bootKernel(); 

    $this->container = static::$kernel->getContainer(); 
    $this->em = $this->getEntityManager(); 
} 

が、テストはTwig_Envを使用する場合残念ながら、それはのRuntimeExceptionを修正doesntの は

http://symfony.com/doc/master/cookbook/testing/doctrine.htmlは私がから私のコンストラクタを変更ご覧ください。

+1

多分[このページ](http://symfony.com/doc/2.8/components/dependency_injection/synthetic_services.html)が参考になります。 –

+0

しかし、AppKernelがカーネルインスタンスを設定しましたか?ユニットテストは同じブートストラップクラスを通過します。 – Rufinus

+0

はい、そうです。私はあなたのケースで何が起こっているのか本当に知りません、私はちょうどそのページが良い場所になるかもしれないと思った... –

答えて

8

テストケースのコンストラクタでカーネルを起動しないでください。これにより、最初のテストが実行された後にシャットダウンされます(https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php#L186-L189参照)。テストケースのsetUp()メソッドでカーネルをブートする必要があります。

+0

あなたのコメントに応じて回答を編集してください(あなたの答えにリンクがありません) –

+0

通知ありがとうございました – xabbuh

+0

ありがとうございますxabbuh。正確に私たちの問題。 'setUpBeforeClass()'ではなく 'setUp()'メソッドでカーネルを起動するだけで簡単です。 – Wulf

関連する問題