April 13, 2016 Javier Eguiluz

In Symfony 2.8 we added a feature to easily mock the clock in time sensitive tests. This reduces the risk of having transient tests, which fail randomly and make your test suite unreliable.

Besides time, the network connection is the other main cause of transient tests. That's why Symfony 3.1 adds a feature to mock the network in DNS sensitive tests. Specifically, the PHPUnit Bridge now provides mocks for these PHP functions:

Consider the following test that uses the checkMX option of the Email constraint to check the validity of the email domain:

1 2 3 4 5 6 7 8 9 10 11 12 13 use Symfony\Component\Validator\Constraints\Email ; class MyTest extends \PHPUnit_Framework_TestCase { public function testEmail () { $validator = ... $constraint = new Email ([ 'checkMX' => true ]); $result = $validator -> validate ( [email protected]' , $constraint ); // ... }

Add the @dns-sensitive annotation to the test class to avoid making a real network connection. Then, use the DnsMock::withMockedHosts() method to configure the data you expect to get for the given hosts:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 use Symfony\Component\Validator\Constraints\Email ; /** * @group dns-sensitive */ class MyTest extends \PHPUnit_Framework_TestCase { public function testEmails () { DnsMock :: withMockedHosts ([ 'example.com' => [[ 'type' => 'MX' ]]]); $validator = ... $constraint = new Email ([ 'checkMX' => true ]); $result = $validator -> validate ( [email protected]' , $constraint ); // ... }

This test will now execute without making any real network connection. In addition to being faster to execute, this test will never fail again due to the network condition.

The withMockedHosts() method configuration is defined as an array. The keys are the mocked hosts and the values are arrays of DNS records in the same format returned by dns_get_record , so you can simulate diverse network conditions: