Issue
I am not able to understand why below two tests are not giving the same result.
@Service
public class SomeManager{
private final SomeDependency someDependency;
@Autowired
public SomeManager(SomeDependency someDependency){
this.someDependency = someDependency;
}
public List<returnType> methodToTest(Arg arg){
List<JsonObject> jo = someDependency.search(arg);
return jo.stream().map(returnType::parse).collect(Collectors.toList());
}
}
Test with any()
. This Test pass.
@RunWith(SpringJUnit4ClassRunner.class)
public class TestMethodToTest(){
@Test
public void TestMethod(){
SomeDependency someDependency = mock(SomeDependency.class);
List<JsonObject> expected := \some valid list of JsonObject\
// Here I used any() method.
when(someDependency.search(any())).thenReturn(expected);
SomeManager someManager = new SomeManager(someDependency);
List<returnType> actual = someManager.methodToTest(any(Arg.class));
assertArrayEquals(acutal.toArray(), expected.stream().map(returnType::parse).toArray());
}
}
But since search(Arg arg)
method of SomeDependency
takes parameter of class Arg
so I changed above test like this:
@RunWith(SpringJUnit4ClassRunner.class)
public class TestMethodToTest(){
@Test
public void TestMethod(){
SomeDependency someDependency = mock(SomeDependency.class);
List<JsonObject> expected := \some valid list of JsonObject\
// Here I used any(Arg.class) method.
when(someDependency.search(any(Arg.class))).thenReturn(expected);
SomeManager someManager = new SomeManager(someDependency);
List<returnType> actual = someManager.methodToTest(any(Arg.class));
assertArrayEquals(acutal.toArray(), expected.stream().map(returnType::parse).toArray());
}
}
This second test fails with output java.lang.AssertionError: array lengths differed, expected.length=1 actual.length=0
.What's the possible reason behind this?
Note: The value expected.length=1
in output depends on what value is provided by the user as valid list of json objects in the test.
Solution
The difference stems from the fact that any
matches null, while anyClass
does not match null. See ArgumentMatchers javadoc:
any()
Matches anything, including nulls and varargs.any(Class<T> type)
Matches any object of given type, excluding nulls.
You are passing null to your method under test here:
List<returnType> actual = someManager.methodToTest(any(Arg.class));
any()
returns null which you pass to method under test.
Note that using argument matchers this way is illegal - you should only call them inside calls to when
and verify
. You should pass a real instance of Arg
to method under test.
See Mockito javadoc
Matcher methods like any(), eq() do not return matchers. Internally, they record a matcher on a stack and return a dummy value (usually null). This implementation is due to static type safety imposed by the java compiler. The consequence is that you cannot use any(), eq() methods outside of verified/stubbed method.
Answered By - Lesiak
Answer Checked By - Katrina (JavaFixing Volunteer)