Matchers
Most of the time expectations specify literal parameter values that are compared for equality against the actual parameters of invoked methods. For example:
allowing (calculator).add(2,2); will(returnValue(5));
Sometimes, however, you will need to define looser constraints over parameter values to clearly express the intent of the test or to ignore parameters (or parts of parameters) that are not relevant to the behaviour being tested. For example:
allowing (calculator).sqrt(with(lessThan(0)); will(throwException(new IllegalArgumentException()); oneOf (log).append(with(equal(Log.ERROR)), with(stringContaining("sqrt"));
Loose parameter constraints are defined by specifying matchers
for each parameter. Matchers are created by factory methods, such as
lessThan
, equal
and
stringContaining
in the example above, to ensure that the
expectation is easy to read. The result of each factory method must be
wrapped by a call to the with
method.
An expectation that uses parameter matchers must use the "with" method to wrap every parameter, whether a matcher function or a literal value.
Factory methods for commonly used matchers are defined in the
Expectations
class. More matchers are defined as static methods in the
org.hamcrest.Matchers
class. If you need these, statically
import thse Matchers into your test code:
import static org.hamcrest.Matchers.*;
Matchers can be combined to tighten or loosen the specification if necessary. The set of matchers is extensible1 so you can write new matchers to cover unusual testing scenarios.
Basic Matchers
Object Equality
The most commonly used matcher is equal
, which specifies
that the received argument must be equal to a given value. The code below,
for example, specifies that the method "doSomething" must be called with
one argument of value 1.
oneOf (mock).doSomething(with(equal(1)));
The equalTo
constraint uses the equals
method
of the expected value to compare the expected and actual values for
equality. Null values are checked beforehand, so it is safe to specify
equal(null)
or apply the matcher to a null actual value.
Arrays are treated as a special case: two arrays are considered equal if
they are the same size and all their elements are considered equal.
Object Identity
The same
matcher specifies that the actual value of the
argument must be the same object as the expected value. This is a tighter
constraint than equal
, but is usually what you want for
arguments that pass references to behavioural objects. The following code
specifies that method "doSomething" will be called with one argument that
refers to the same object as expected.
Object expected = new Object(); oneOf (mock).doSomething(with(same(expected)));
As a rule of thumb, use equal
for value objects and
same
for behavioural objects.
Substring
The stringContaining
matcher specifies that the expected
argument must be a string that contains the given substring. The following
code specifies that method "doSomething" must be called with an argument
that is a string containing the text "hello".
oneOf (mock).doSomething(with(stringContaining("hello")));
The stringContaining
matcher is especially useful for
testing string contents but isolating tests from the exact details of
punctuation and formatting. For example, the code above would accept any
of the following argument values: "hello world"; "hello, world"; "hello!";
and so on.
Null or Not Null
The matchers aNull<T>(Class<T>)
and
aNonNull<T>(Class<T>)
specify that an argument is
null or is not null, respectively. The following code specifies that
method "doSomething" must be called with two Strings, the first must be
null and the second must not be null.
oneOf (mock).doSomething(with(aNull(String.class)), aNonNull(String.class)));
Anything
The any<T>(Class<T>)
constraint specifies that
any value of the given type is allowed. This is useful for ignoring
arguments that are not relevant to the scenario being tested. Judicious
use of the any
constraint ensure that your tests are flexible
and do not require constant maintenance when tested code changes. The
following code specifies that the method "doSomething" must be called with
two arguments, the first of which is equal to 1 and the second of which is
ignored in this test.
oneOf (mock).doSomething(with(eq(1)), with(any(String.class)));
Numeric Equality with Error Margin
An overloaded version of the equal
constraint specifies
floating point values as equal to another value with some margin of error
to account for rounding error. The following code specifies that the
method "doSomething" will be called with one argument of value 1 plus or
minus 0.002.
oneOf (mock).doSomething(with(equal(1, 0.002)));
Combining Matchers
Matchers can be composed to create a tighter or looser specification. Composite matchers are themselves matchers and can therefore be further composed.
Not — Logical Negation
The not
matcher specifies that the actual argument must
not match a given matcher. The following code specifies that the
method "doSomething" must be called with an argument that is not equal to
1.
oneOf (mock).doSomething(with(not(eq(1)));
AllOf — Logical Conjunction
The allOf
matcher specifies that the actual argument must
meet all of the matchers given as arguments. The following code
specifies that the method "doSomething" must be called with a string that
contains the text "hello" and the text "world".
oneOf (mock).doSomething(with(allOf(stringContaining("hello"), stringContaining("world"))));
AnyOf — Logical Disjunction
The anyOf
matcher specifies that the actual argument must
meet at least one of the matchers given as arguments. The
following code specifies that the method "doSomething" must be called with
a string that either contains the text "hello" or the text "howdy".
oneOf (mock).doSomething(with(anyOf(stringContains("hello"), stringContains("howdy"))));