-
Notifications
You must be signed in to change notification settings - Fork 27
Constraints
This is a tutorial for using https://github.com/etsy/phpunit-extensions/tree/master/PHPUnit/Extensions/Constraint.
Constraints are derived from Hamcrest matchers. Hamcrest is a framework for creating matchers, allowing match rules to be defined declaratively (see). In PHPUnit the two most common usages of constraints are:
- Creating new assertions with
assertThat
- Advanced matching of parameters in Mock Objects
You may encounter a situation where you would like to use assertEquals
to compare two object, but it turns out you only want to do so on a subset of fields. For example, that pesky ORM object that contains fields for transient (for lack of a better word) database connections.
Most will just add multiple assertions to the test, but then miss out on possibly valuable information from non-executed assertions. Some will do a bit better by writing the custom assertion, but will miss out on the value added by having a constraint.
Sadly, most miss out on constraints because it is yet another class, and if you are being rigorous, yet another file.
Since most custom assertions are checking equality of objects on a subset of fields, it seemed to make sense to create the EqualsClosure
constraint. This way all you have to do is fill out a closure like it was that if statement in your custom assertion or constraint matches()
function. Simple!
Example:
class UserAsserts { public static function equals($expected) { return new PHPUnit_Extensions_Constraint_EqualsClosure( $expected, function ($expected, $actual) { return $expected->id === $actual->id && $expected->first === $actual->first && $expected->last === $actual->last; } ); } public static function assertEquals($expected, $actual, $message='') { $this->assertThat( $actual, self::equals($expected), $message ); } public static function assertNotEquals($expected, $actual, $message='') { $this->assertThat( $actual, new PHPUnit_Framework_Constraint_Not( self::equals($expected) ), $message ); } }
More Examples: https://github.com/etsy/phpunit-extensions/blob/master/Tests/Extensions/Constraint/EqualsClosureTest.php
This constraint requires that the actual array contains at least one of each of the expected items.
Example:
$object = $this->getMock('SomeClass') ->expects($this->any()) ->method('doSomething') ->with(new PHPUnit_Extensions_Constraint_HasItems(array(1, 2, 3))); ... // This will pass because we passed in an array that contains at least a 1, a 2, and a 3 $object->doSomething(array(4, 3, 2, 1)); // This will fail because we passed in an array that was missing a 1 $object->doSomething(array(3, 2, 0));
More Examples: https://github.com/etsy/phpunit-extensions/blob/master/Tests/Extensions/Constraint/HasItemsTest.php
Please use PHPUnit_Framework_Constraint_SameSize
as PHPUnit 3.6
This constraint allows verifying that the actual content of the string is as expected without needing to match leading or trailing whitespace, or having to get tabs and newlines correct.
Example:
$object = $this->getMock('SomeClass') ->expects($this->any()) ->method('doSomething') ->with(new PHPUnit_Extensions_Constraint_StringMatchIgnoreWhitespace("spaces do not matter")); ... // This will pass because the string after reducing white space are "spaces do not matter" $object->doSomething("spaces\ndo\tnot matter "); // This will fail because this string is NOT equivalent to "spaces do not matter" $object->doSomething("but the not whitespace characters do!");
More Examples: https://github.com/etsy/phpunit-extensions/blob/master/Tests/Extensions/Constraint/StringMatchIgnoreWhitespaceTest.php
This constraint requires that the actual array contains a particular key and value pair.
Example:
$object = $this->getMock('SomeClass') ->expects($this->any()) ->method('doSomething') ->with(new PHPUnit_Extensions_Constraint_ArrayHasKeyValuePair('key', 'value')); ... // This will pass because we passed in an array that contains at least a 1, a 2, and a 3 $object->doSomething(array('key' => 'value'); // This will fail because we passed in that does not pair 'key' with 'value'. $object->doSomething(array('key' => 'not_value', 'not_key' => 'value'));
More Examples: https://github.com/etsy/phpunit-extensions/blob/master/Tests/Extensions/Constraint/ArrayHasKeyValuePairTest.php