1. Introduction
If you have ever written a Unit test using the mocking Framework Mockito, there is a big chance that you have already encountered this exception. In this quick tutorial, you will learn what the InvalidUseOfMatchersException is about and how to fix it.
2. What Mockito Says about InvalidUseOfMatchersException
As its name suggests, this exception occurs whenever you misuse the matchers in your code. Typically, this happens when you combine matchers and raw values in a test.
3. How to Reproduce
Consider the following class under test Calculator.java
:
//Calculator.java
package com.kloudly.exception;
public class Calculator {
private OperationFormatter formatter;
public Calculator(OperationFormatter formatter){
this.formatter = formatter;
}
public String calculate(double firstOperand, double secondOperand, char operator){
double result = 0d;
switch (operator){
case '+':{
result = add(firstOperand,secondOperand);
return this.formatter.format(operator,firstOperand,secondOperand,result);
}
case '-':{
result = subtract(firstOperand,secondOperand);
return this.formatter.format(operator,firstOperand,secondOperand,result);
}
case '*':{
result = multiply(firstOperand,secondOperand);
return this.formatter.format(operator,firstOperand,secondOperand,result);
}
case ':':{
result = divide(firstOperand,secondOperand);
return this.formatter.format(operator,firstOperand,secondOperand,result);
}
default:
throw new IllegalArgumentException("Unsupported operation :"+operator);
}
}
private double divide(double firstOperand, double secondOperand) {
if(secondOperand == 0)
throw new IllegalArgumentException("Second argument must not be zero!");
return firstOperand / secondOperand;
}
private double multiply(double firstOperator, double secondOperand) {
return firstOperator * secondOperand;
}
private double subtract(double firstOperand, double secondOperand) {
return firstOperand - secondOperand;
}
private double add(double firstOperand, double secondOperand) {
return firstOperand + secondOperand;
}
}
The Calculator
class depends on another class OperationFormatter
:
//OperationFormatter.java
package com.kloudly.exception;
public class OperationFormatter {
public String format(char operator, double firstOperand, double secondOperand, double result){
return firstOperand + " " + operator + " "+ secondOperand +" = " + result;
}
}
Let’s assume we want to test the Calculator
class in a Unit context. We will have to mock the OperationFormatter
class.
Below is the code snippet of CalculatorTest
class:
package com.kloudly.exception;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class CalculatorTest {
private static Calculator calculator;
private static OperationFormatter formatter;
@BeforeAll
static void setUp(){
formatter = mock(OperationFormatter.class);
calculator = new Calculator(formatter);
}
@Test
public void testInvalidUseOfMatchers() {
//Given
String expectedResult = "1 + 1 = 2";
when(formatter.format('+',anyDouble(),anyDouble(),anyDouble())).thenReturn(expectedResult);
//When
String result = calculator.calculate(1,1,'+');
//Then
assertEquals(expectedResult,result);
}
}
If you run the CalculatorTest
class, you will get the following output:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
4 matchers expected, 3 recorded:
-> at com.kloudly.exception.CalculatorTest.testInvalidUseOfMatchers(CalculatorTest.java:26)
-> at com.kloudly.exception.CalculatorTest.testInvalidUseOfMatchers(CalculatorTest.java:26)
-> at com.kloudly.exception.CalculatorTest.testInvalidUseOfMatchers(CalculatorTest.java:26)
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(any(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(any(), eq("String by matcher"));
For more info see javadoc for Matchers class.
This exception happens here because of this line : when(formatter.format('+',anyDouble(),anyDouble(),anyDouble())).thenReturn(expectedResult);
As you can see, we are combining the raw value '+'
with the matcher anyDouble()
.
4. How to Fix the Exception
Ensure you are not mixing raw values and matchers in your mock configurations. For the test above, you must replace the raw value '+'
with a matcher equivalent eq('+')
.
@Test
public void testInvalidUseOfMatchers() {
//Given
String expectedResult = "1 + 1 = 2";
when(formatter.format(eq('+'),anyDouble(),anyDouble(),anyDouble())).thenReturn(expectedResult);
//When
String result = calculator.calculate(1,1,'+');
//Then
assertEquals(expectedResult,result);
}
5. Conclusion
In this brief tutorial, you learned about the InvalidUseOfMatchersException and how to fix it. Learn more about Common Java Exception.
You can find the complete code of this article here in GitHub
Pingback: How to Fix UnfinishedStubbingException