Вопрос

I've an issue with symfony and phpunit. Our peoject is growing bigger and bigger. So we decided to activate process isolation for phpunit because the server couldn't stand the amount of tests anymore (Not enough RAM). Since then all test which send mails aren't working anymore. Could someone please help us? The test below works perfectly fine if processIsolation="false" but it fails if processIsolation="true"

Versions:

  • symfony 2.1.8-dev

  • phpunit 3.7.9

ERROR Message

Project\AppBundle\Tests\MailTest::testSendMail PHPUnit_Framework_Exception: PHP Fatal error: Class 'Swift_Message' not found in /var/www/project/src/Project/AppBundle/Tests/MailTest.php

Test

public function testSendMail()
{
    $client = static::createClient();

    $message = \Swift_Message::newInstance();
    $message->setFrom('example@example.com')
        ->setTo('example@example.com')
        ->setSubject('Subject')
        ->setBody('Hello World')
        ->setContentType('text/html');

    $client->getContainer()->get('mailer')->send($message);
    $this->assertTrue(true);
}

phpunit.xml

<phpunit
    backupGlobals="false"
    backupStaticAttributes="false"
    colors="true"
    convertErrorsToExceptions="true"
    convertNoticesToExceptions="true"
    convertWarningsToExceptions="true"
    bootstrap="./autoload.php"
    processIsolation="true"
    stopOnFailure="false"
    syntaxCheck="false" >

    <testsuites>
        <testsuite name="Project Test Suite">
            <directory>../src/Project/AppBundle/Tests/MailTest.php</directory>
        </testsuite>
</testsuites>
</phpunit>
Это было полезно?

Решение

This error is caused because Switfmailer defines a constant SWIFT_REQUIRED_LOADED after it installs it's autoloader. The autoloader checks this constant, and if it's already defined, refuses to install the autoloader. In process isolation, PHPUnit ensures that all defined constants are re-defined in the processs that gets spawned to run the test. Unfortunately, this means that SWIFT_REQUIRED_LOADED is defined in the test process, so the autoloader doesn't load (see "swift_required.php" in the swiftmailer source directory). Note that if you turn off include global state for the test via annotations your tests still won't work, because the bootstrap file is passed to the test process via the __PHPUNIT_BOOTSTRAP global variable (see TestCaseMethod.tpl in the PHPUnit directory). Without the globals, this global is undefined in the test process and the bootstrap file is not included breaking the tests.

The only work around that I found that works was to replace the line $constants = PHPUnit_Util_GlobalState::getConstantsAsString(); with $constants = ''; in the run method of TestCase.php in the PHPUnit source distribution. If your code relies on global constants to be defined before your test cases run this fix obviously won't work for you (class constants are a different story); unless said constants will be redefined safely in the course of running your test cases.

Другие советы

This is caused by a problem related to the swiftmailer autoloader.

I encountered the same problem and fixed it in a forked repository of swiftmailer.

Here you can find the PR for the fix: https://github.com/swiftmailer/swiftmailer/pull/416.

If you do not wish to wait until this is merged you can use my repository by adding this to your composer.json.

"require": {
    "swiftmailer/swiftmailer": "dev-master as 5.0.x-dev"
},
"repositories": [
    {
        "type": "vcs",
        "url":  "https://github.com/NickStemerdink/swiftmailer.git"
    }
]

UPDATE: The PR has been merged in the meanwhile, so you can just update to the latest swiftmailer version.

Does it work if you first instantiate $message and call static::createClient afterwards?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top