Testing Symfony2 emails with Behat 3

1.9k Views Asked by At

I followed the Behat 2.5 docs to test mails. After a few tweaks to match Behat 3 I have ended with the following code (I have removed non-relevant parts):

public function getSymfonyProfile()
{
    $driver = $this->mink->getSession()->getDriver();

    if (!$driver instanceof KernelDriver) {
        // Throw exception
    }

    $profile = $driver->getClient()->getProfile();
    if (false === $profile) {
        // Throw exception
    }

    return $profile;
}

/**
 * @Then I should get an email with subject :subject on :email
 */
public function iShouldGetAnEmail($subject, $email)
{
    $profile   = $this->getSymfonyProfile();
    $collector = $profile->getCollector('swiftmailer');

    foreach ($collector->getMessages() as $message) {
        // Assert email
    }

    // Throw an error if something went wrong
}

When I run this test, it throws the following error:

exception 'LogicException' with message 'Missing default data in Symfony\Bundle\SwiftmailerBundle\DataCollector\MessageDataCollector' in vendor/symfony/swiftmailer-bundle/Symfony/Bundle/SwiftmailerBundle/DataCollector/MessageDataCollector.php:93
Stack trace:
    #0 vendor/symfony/swiftmailer-bundle/Symfony/Bundle/SwiftmailerBundle/DataCollector/MessageDataCollector.php(122): Symfony\Bundle\SwiftmailerBundle\DataCollector\MessageDataCollector->getMailerData('default')
    #1 features/bootstrap/FeatureContext.php(107): Symfony\Bundle\SwiftmailerBundle\DataCollector\MessageDataCollector->getMessages()

My profiler is configured as follows:

# app/config/config_test.yml
framework:
    test: ~
    profiler:
        enabled: true
        collect: true

It seems that the Profile is correctly loaded and the MessageDataCollector from Swiftmailer does exist, but it is not doing its work as expected. Any clue to solve this?

2

There are 2 best solutions below

1
On BEST ANSWER

Maybe the issue you have has been fixed as I do not have this anymore (I'm using Behat v3.0.15, BrowserKit driver 1.3.* and Symfony v2.6.6).

I managed to reproduce your error but only when I forgot to enable profiler data collecting:

profiler:
    collect: false

Once this problem solved (the configuration you provided solving the problem for me) I managed to check emails in my Behat tests. Two solutions for this:

Solution #1: Intercepting redirects globally

If it does not break all your other tests you can do so by configuring your web profiler as follows:

web_profiler:
    intercept_redirects: true

Solution #2: Preventing client to follow redirections temporarily

For my part, intercepting redirections globally in the configuration broke most of my other functional tests. I therefore use this method instead.

As preventing redirections allows mainly to check data in the data collectors I decided to use a tag @collect on each scenario requiring redirect interception. I then used @BeforeScenario and @AfterScenario to enable this behaviour only for those scenarios:

/**
 * Follow client redirection once
 *
 * @Then /^(?:|I )follow the redirection$/
 */
public function followRedirect()
{
    $this->getDriver()->getClient()->followRedirect();
}

/**
 * Restore the automatic following of redirections
 *
 * @param BeforeScenarioScope $scope
 *
 * @BeforeScenario @collect
 */
public static function disableFollowRedirects(BeforeScenarioScope $scope)
{
    $context = $scope->getEnvironment()->getContext(get_class());
    $context->getDriver()->getClient()->followRedirects(false);
}

/**
 * Restore the automatic following of redirections
 *
 * @param AfterScenarioScope $scope
 *
 * @AfterScenario @collect
 */
public static function restoreFollowRedirects(AfterScenarioScope $scope)
{
    $context = $scope->getEnvironment()->getContext(get_class());
    $context->getDriver()->getClient()->followRedirects(true);
}
6
On

It's not the answer your are looking for, but I'm pretty sure it will suits your needs (perhaps more).
If I can suggest, try using Mailcatcher with this bundle: https://packagist.org/packages/alexandresalome/mailcatcher
You'll be able to easily tests if emails are sent, what's their subject, follow a link in the body, and so on...
Many steps are included with this bundle.