Home Arrow Icon Knowledge base Arrow Icon Global Arrow Icon How can I use Hamcrest matchers with Mockito


How can I use Hamcrest matchers with Mockito


Using Hamcrest matchers with Mockito allows you to leverage the powerful matching capabilities of Hamcrest within your Mockito tests. Here's a detailed guide on how to integrate and use them effectively:

Introduction to Hamcrest and Mockito Integration

Hamcrest provides a rich set of matchers that can be used to assert the behavior of your code. Mockito, on the other hand, is a popular mocking framework for Java. Starting from Mockito 2, the integration with Hamcrest was improved to avoid version conflicts, and it provides a way to use Hamcrest matchers directly in Mockito stubbing and verification.

Using `argThat` with Hamcrest Matchers

To use Hamcrest matchers in Mockito, you need to use the `argThat` method provided by `MockitoHamcrest`. This method converts a Hamcrest matcher into a Mockito matcher, allowing you to use it in stubbing and verification.

Here's an example:

java
import static org.mockito.hamcrest.MockitoHamcrest.argThat;
import static org.hamcrest.Matchers.startsWith;

// Create a mock object
MyClass mock = Mockito.mock(MyClass.class);

// Stubbing using Hamcrest matcher
when(mock.giveMe(argThat(startsWith("Hello")))).thenReturn("World");

// Verification using Hamcrest matcher
verify(mock).giveMe(argThat(startsWith("Hello")));

In this example, `startsWith("Hello")` is a Hamcrest matcher that checks if a string starts with "Hello". The `argThat` method wraps this matcher so it can be used in Mockito's `when` and `verify` methods.

Creating Custom Hamcrest Matchers

If the existing Hamcrest matchers do not meet your needs, you can create custom matchers by extending `org.hamcrest.BaseMatcher`. Here's how you can create a custom matcher:

java
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;

public class CustomMatcher extends BaseMatcher {
    private final String expected;

    public CustomMatcher(String expected) {
        this.expected = expected;
    }

    @Override
    public boolean matches(Object item) {
        if (item == null) return false;
        return ((String) item).contains(expected);
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("a string containing '" + expected + "'");
    }
}

You can then use this custom matcher in your tests:

java
CustomMatcher customMatcher = new CustomMatcher("World");
when(mock.giveMe(argThat(customMatcher))).thenReturn("Hello World");

Handling Primitive Types

When using Hamcrest matchers with primitive types (like `int`, `double`, etc.), you need to be careful about auto-unboxing. In rare cases, this can lead to `NullPointerExceptions`. To avoid this, Mockito provides methods like `intThat`, `floatThat`, etc., which you should use instead of `argThat` for primitive types:

java
import static org.mockito.hamcrest.MockitoHamcrest.intThat;
import static org.hamcrest.Matchers.equalTo;

when(mock.giveMe(intThat(equalTo(5)))).thenReturn("Five");

Conclusion

Integrating Hamcrest matchers with Mockito enhances your testing capabilities by allowing you to use more expressive and flexible matchers in your stubbing and verification. By using `argThat` and creating custom matchers, you can write more robust and readable tests.

Citations:
[1] https://site.mockito.org/javadoc/current/org/mockito/hamcrest/MockitoHamcrest.html
[2] https://www.lambdatest.com/automation-testing-advisor/selenium/classes/org.mockito.hamcrest.MockitoHamcrest
[3] https://stackoverflow.com/questions/33351500/mockito-jmockit-hamcrest-matchers-how-to-verify-lists-collections
[4] https://www.javacodegeeks.com/2015/11/hamcrest-matchers-tutorial.html
[5] https://www.lambdatest.com/automation-testing-advisor/selenium/methods/org.mockito.hamcrest.MockitoHamcrest.MockitoHamcrest
[6] https://www.javacodegeeks.com/2015/11/custom-hamcrest-matchers.html
[7] https://stackoverflow.com/questions/8348046/mockitos-matcher-vs-hamcrest-matcher
[8] https://stackoverflow.com/questions/20441594/mockito-and-hamcrest-how-to-verify-invocation-of-collection-argument
[9] https://www.lambdatest.com/automation-testing-advisor/selenium/methods/org.mockito.internal.hamcrest.MatcherGenericTypeExtractorTest.describeMismatch
[10] https://www.lambdatest.com/automation-testing-advisor/selenium/methods/org.mockito.hamcrest.MockitoHamcrest.argThat