Issue
I have a method hello(HttpServletRequest request)
that needs to be unit tested. In this method, I do something like this Cookie cookie = WebUtils.getCookie(request, cookie_name)
. So basically, I extract the cookie here and do my stuff. This is how my test class looks like:
@Test
public void testHello() {
Cookie cookie = new Cookie(cookie_name, "");
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
Mockito.when(WebUtils.getCookie(request, cookie_name)).thenReturn(cookie);
// call the hello(request) and do assert
}
So whenever I try to mock and return this cookie, I end up with something like this in my stack trace.
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
Cookie cannot be returned by getCookies()
getCookies() should return Cookie[]
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
- with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
Inside WebUtils.getCookie()
, it basically does request.getCookies()
and iterates the array to get the correct one. This WebUtils comes from Spring Web. As you can see I have returned some value for that as well. Still getting this error. Has anyone faced this issue? How can I workaround this?
Solution
Following up on @Ajinkya comment, I think this is what he wanted to express:
The getCookie method might looks something like this (I just used some version of it, so there might have been some changes in the version you are using)
public static Cookie getCookie(HttpServletRequest request, String name) {
Assert.notNull(request, "Request must not be null");
Cookie cookies[] = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (name.equals(cookie.getName())) {
return cookie;
}
}
}
return null;
}
Since you mocked your request you can control what getCookies() is returning.
To make this method working (without mocking it), you just would need to return a mock instead of a real Cookie from getCookies()
.
Cookie mockCookie = Mockito.mock(Cookie.class);
Mockito.when(mockCookie.getName()).thenReturn(cookie_name);
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{mockCookie});
Changing it to this and the static method can do its work as usual.
You wouldn't need bother mocking it.
Answered By - second