Issue
I have this method which I want to test using mockito
public boolean verifyState(HttpServletRequest request) {
String stateToken = getCookieByName(request, STATE_TOKEN);
String authToken = getCookieByName(request, AUTHN);
boolean isValidState = !stateToken.isEmpty() && !authToken.isEmpty();
if (isValidState) {
return true;
}
else {
return false;
}
}
It does two calls to getCookieName(), which has this implementation.
public String getCookieByName(HttpServletRequest request, String cookieName) {
try {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(cookieName)) {
return cookie.getValue();
}
}
}
} catch (Exception e) {
ExceptionLogger.logDetailedError("CookieSessionUtils.getCookieByName", e);
log.error("Error on Cookie " + e.getMessage());
}
return "";
}
I then have this for my tests:
@WebMvcTest(value = CookieSessionUtils.class, includeFilters =
{@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {ApiOriginFilter.class})})
class CookieSessionUtilsTest {
@Autowired
private CookieSessionUtils cookieSessionUtils;
@Mock
private HttpServletRequest request;
@BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testVerifyState() {
Cookie mockCookie1 = Mockito.mock(Cookie.class);
Cookie mockCookie2 = Mockito.mock(Cookie.class);
when(mockCookie1.getName()).thenReturn("stateToken");
when(mockCookie1.getValue()).thenReturn("stateToken");
when(mockCookie2.getName()).thenReturn("authn");
when(mockCookie2.getValue()).thenReturn("authn");
when(request.getCookies()).thenReturn(new Cookie[]{mockCookie1, mockCookie2});
when(cookieSessionUtils.getCookieByName(request, "stateToken")).thenReturn("stateToken");
when(cookieSessionUtils.getCookieByName(request, "authn")).thenReturn("authn");
assertTrue(cookieSessionUtils.verifyState(request));
}
However, it's always failing returning false falling into the return ""
for the getCookieByName()
method which seems to be triggered multiple times and having the value for getName() and getValue() overwritten by the other cookie, so it fails on (cookie.getName().equals(cookieName))
. Not sure what I'm doing wrong.
Thank you.
Solution
No need to be so complicated. For mocking the servlet stuff, you can simply use the mock implementation provided by spring-test. It is more convenient to use than Mockito.
You can simply write your test case as :
@Test
public void testVerifyState() {
MockHttpServletRequest request = MockMvcRequestBuilders.get("/dummy")
.cookie(new MockCookie("stateToken", "stateToken"))
.cookie(new MockCookie("authn", "authn"))
.buildRequest(new MockServletContext());
assertTrue(cookieSessionUtils.verifyState(request));
}
Also , if the CookieSessionUtils
that you are testing is just an utility class which does not have other spring bean dependencies, you can further simplify your test to just a plain JUnit test rather than a @WebMvcTest
.
Answered By - Ken Chan
Answer Checked By - Pedro (JavaFixing Volunteer)