Working with Strings

Hamcrest also provides several matchers for working with strings. Here are some examples:

I recommend you use the more expressive matchers whenever possible...

Obviously, the equalTo() and identicalTo() matchers work with strings, and they behave exactly as you would expect them to. But as you can see, Hamcrest provides other string-specific equality matchers. As their names imply, the equalToIgnoringCase() and equalToIgnoringWhiteSpace() matchers match strings by ignoring case and whitespace, respectively.

Other matchers, such as startsWith() and endsWith(), check if the specified sub-string is at the beginning or end of the actual string. The containsString() matcher checks if the string contains the supplied sub-string. The containsString() matcher can also be extended with containsStringIgnoringCase(), adding case insensitivity.

The matchesPattern() matcher incorporates regular expressions to find a match in the string. You can use any regular expression, and in many cases, this solution is necessary in more complex strings. In any case, I recommend you use the more expressive matchers whenever possible and only resort to regular expressions if absolutely necessary; doing so makes your code more readable by everyone.

Matching Empty Strings

It's common to test if a string is empty. Hamcrest has you covered.

Yes, there are many matchers for checking if a string is empty. Each variant has a version with "is" in front of it. Essentially, emptyString() and isEmptyString() are identical, and the same is true for the other matchers. The nonEmptyString() and isNonEmptyString() matchers can also be written like this:

But of course, those variants can add extra verbosity, making it more difficult to understand the code at first glance.

Inclusions and Exclusions

Here are some nice approaches to determine whether or not a variable belongs to a group:

These examples use strings, but you can use these matchers with variables like objects, arrays, numbers, etc. The anyOf() and noneOf() matchers determines whether or not the expected variable resides in the provided list of values.

The other two matchers, both() and either(), are commonly used with the andAlso() and orElse() modifiers. These are equivalents of:

Finally, anything() matches... well, anything. It has an optional string parameter for meta data purposes, helping anyone reading the test to better understand why an assertion should always match.

Arrays

The array matchers are probably the most complex and useful matchers provided by Hamcrest. The code in this section provides a list of tricks to make complicated array-based assertions change into code that reads like well written prose.

Please Note: I make no difference between arrays and hashes in these examples. I only talk about arrays, but everything applies to hashes as well.

Array Equality

These methods highlight different ways to compare the equality of two arrays. The first version uses the misleadingly named anArray() matcher. It actually it compares the two arrays element by element. On failure, only the first set of unequal elements are displayed in the error message.

The second version, using equalTo(), also compares each element in the arrays, but it outputs both arrays in their entirety on failure. Naturally, the length of your arrays will determine which matcher you use. Reading large arrays can be difficult.

Partial Array Matches

In many cases, we simply want to check if an array contains certain elements. Hamcrest has us covered.

The hasItemInArray() and hasValue() matchers are identical; they both check if the provided value or matcher result exists in the array. Providing a value as an argument is equivalent to using equalTo(). Therefore, these are identical: hasValue(2) and hasValue(equalTo(2)).

The next two matchers, arrayContaining() and contains(), are also identical. They check, in order, that every element of the array satisfies the matcher, or that every element is equal to the specified values.

Finally, as you can easily deduce from the above example, arrayContainingInAnyOrder() and containsInAnyOrder() are the same as the previous two matchers. The only difference is that they do not care about the order.

Matching Array Keys

The matchers hasKeyInArray() and hasKey() check if the given argument matches any keys in the array, while the last two matchers return true only if both key and value are found. So, a matcher like hasEntry('one', 2); would have failed our test because in our array, at key 'one' we have the value 1 and not 2.

Please Note: It is recommended to use the shorter version (hasKey) when it is obvious from the variable's name that it is an array. Whoever reads your code may be confused about the type of the variable, in which case, (hasKeyInArray) may be more helpful.

Array Sizes

You can easily check the size of an array with three matchers:

The arrayWithSize() matcher checks for a specific size, nonEmtpyArray() checks if the array has at least one element, and emptyArray() verifies that the given array is empty.

Please Note: There are versions of these three matchers if you prefer iterable objects. Just replace "Array" with "Traversable" like this traversableWithSize().

Checking for Value Types

These are the last matchers. You can practically check for any data type in PHP.

These are self-explanatory. Simply provide a value or object, and use one of the easy-to-use matchers to determine its data type.

Conclusions

Hamcrest PHP is not extensively documented in the official documentation, and I hope this tutorial helped explain the matchers it provides. There are a few matchers not listed in this tutorial, but they are very exotic and rarely used.

Every Hamcrest matcher helps you write tests that read very naturally.

If they are not enough for you, you can add your own matchers for your whatever situation you need them for. I hope you enjoyed this tutorial, and thank you for reading.