Argument matchers in Mockito are powerful tools used to make tests more flexible and robust by allowing you to stub or verify method calls with generic or specific conditions. Here are some common use cases for argument matchers:
Stubbing Generic Behaviors
When you're testing a method that doesn't depend on specific input values, you can use argument matchers like `any()`, `anyString()`, `anyInt()`, etc., to stub its behavior. For example, if you have a method `bool(String str, int i, Object obj)`, you can stub it to return `true` for any input:
java
Foo mockFoo = mock(Foo.class);
when(mockFoo.bool(anyString(), anyInt(), any(Object.class))).thenReturn(true);
This way, no matter what string, integer, or object you pass to `bool()`, it will return `true`.
Matching Specific Values
If you need to match a specific value for one argument while keeping others generic, you can use `eq()` along with other matchers. For instance:
java
when(mockFoo.bool(eq("false"), anyInt(), any(Object.class))).thenReturn(false);
Here, the method will return `false` only if the string argument is `"false"`, regardless of the integer and object values.
Verification
Argument matchers are also useful for verifying that a method was called with certain arguments. You can use `verify()` with matchers to check if a method was invoked with specific or generic conditions:
java
verify(mockFoo).bool(anyString(), anyInt(), any(Object.class));
This verifies that `bool()` was called at least once with any string, integer, and object.
Complex Conditions
Mockito provides additional matchers for more complex conditions, such as `gt()`, `lt()`, `geq()`, `leq()`, which can be used for numeric comparisons. You can also combine matchers using logical operations like `or()`, `and()`, and `not()`:
java
when(mockFoo.bar(any(byte[].class), aryEq(new String[] { "A", "B" }), gt(10))).thenReturn(11);
This stubs the `bar()` method to return `11` if it's called with any byte array, the string array `["A", "B"]`, and an integer greater than `10`.
Custom Matchers
If the built-in matchers aren't sufficient, you can create custom matchers using `argThat()`. This allows you to define a custom condition for matching arguments:
java
ArgumentMatcher hasLuck = file -> file.getName().endsWith("luck");
when(fileFilter.accept(argThat(hasLuck))).thenReturn(true);
This stubs `accept()` to return `true` if the file name ends with `"luck"`.
In summary, argument matchers are versatile tools in Mockito that help you write more flexible and robust tests by allowing generic or specific matching of method arguments during stubbing and verification.
Citations:[1] https://www.digitalocean.com/community/tutorials/mockito-argument-matchers-any-eq
[2] https://www.softwaretestinghelp.com/mockito-matchers/
[3] https://javadoc.io/doc/org.mockito/mockito-core/4.5.1/org/mockito/ArgumentMatchers.html
[4] https://stackoverflow.com/questions/16458136/mockito-invalid-use-of-argument-matchers
[5] https://www.toptal.com/java/a-guide-to-everyday-mockito
[6] https://www.lambdatest.com/automation-testing-advisor/selenium/methods/org.mockito.ArgumentMatchers.argThat
[7] https://stackoverflow.com/questions/7500312/mockito-match-any-class-argument
[8] https://www.jrebel.com/blog/mock-unit-testing-with-mockito
[9] https://stackoverflow.com/questions/73046134/when-should-i-use-argument-matcher-or-passing-argument-directly-when-mockito-uni