Home > Blockchain >  Mockito failing inside internal call for mocked method
Mockito failing inside internal call for mocked method

Time:12-26

I'm trying to mock the return value for a method using the when call from mockito. However, I'm new to this and I may perhaps be misunderstanding how mockito works, since the call is failing inside the method mocked when that calls another method. I thought regardless of how that method is implemented, I should be getting the return value I'm asking for? Or do I need to mock also the internals for that method? I feel that shouldn't be it.

public boolean verifyState(HttpServletRequest request, String s) {

    String stateToken = getCookieByName(request, STATE_TOKEN);
    String authToken = getCookieByName(request, AUTHN);

    boolean isValidState = true;

    if (isValidState) {
        
        try {
            log.info(getEdUserId(stateToken, authToken));

            return true;
        } catch (Exception e) {
            ExceptionLogger.logDetailedError("CookieSessionUtils.verifyState", e);
            return false;
        }
    } else {
        return false;
    }
}

public String getEdUserId(String stateToken, String authToken) throws Exception {
    String edUserId;
    Map<String, Object> jwtClaims;
    jwtClaims = StateUtils.checkJWT(stateToken, this.stateSharedSecret); // Failing here not generating a proper jwt token
    log.info("State Claims: "   jwtClaims);
    edUserId = sifAuthorizationService.getEdUserIdFromAuthJWT(authToken);
    return edUserId;
}

My test:

@ActiveProfiles(resolver = MyActiveProfileResolver.class)
@WebMvcTest(value = CookieSessionUtils.class, includeFilters = {
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {ApiOriginFilter.class, ValidationFilter.class})})
class CookieSessionUtilsTest {

@Autowired
private CookieSessionUtils cookieSessionUtils; // Service class

@Mock
private CookieSessionUtils cookieSessionUtilsMocked; // Both the method under test and the one mocked are under the same class, so trying these two annotations together.

@Mock
private HttpServletRequest request;

@BeforeEach
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void testVerifyState1() throws Exception {

    //...Some mocks for getCookieName

    UUID uuid = UUID.randomUUID();
    when(cookieSessionUtils.getEdUserId(anyString(), anyString()).thenReturn(eq(String.valueOf(uuid))); // When this line runs it fails on verifyState method

    assertTrue(cookieSessionUtils.verifyState(request, ""));
}

enter image description here

UPDATE

Attempt using anyString() instead of eq().

enter image description here

Thank you.

CodePudding user response:

The error is here: when(cookieSessionUtils.getEdUserId(eq("anyString()"), eq("anyString()"))).thenReturn(eq(String.valueOf(uuid)));

It should read like when(cookieSessionUtils.getEdUserId(anyString()), anyString()).thenReturn(uuid); Please refer to the Mockito documentation of Argument matchers.

Because the argument matchers looking for the string "anyString()" they never match the actual parameters the method call is providing and so there is never returned the uuid you expecting.

CodePudding user response:

Your test is broken in a few places.

Setting expectations on a real object

You should call Mockito.when on mocks and spies, not on System under test. Mockito normally reports it with a clear error message, but you throw a NPE from getEdUserId, so this is reported instead. The NPE stems from the fact that both eq and anyString return null, which is passed to the real method.

Invalid use of matchers

As @StefanD explained in his answer eq("anyString()") is not matching any string. It matches only one string "anyString()"

Mixing Mockito and Spring annotations in a WebMvcTest

This is a common error. Mockito does not inject beans to the spring context.

From the code provided it is unclear what CookieSessionUtils is (Controller? ControllerAdvice?) and what is the correct way to test it.

Update

It seems that you are trying to replace some methods under test. A way to do it is to use a Spy. See https://towardsdatascience.com/mocking-a-method-in-the-same-test-class-using-mockito-b8f997916109

An alternative way is to call the real method, but to mock all collaborators: StateUtils and sifAuthorizationService. I would probably go with this one, if you want to test public getEdUserId.

The points above are still valid and need to be resolved in either case.

As the system under test is a Service, I suggest to drop WebMvcTest and test it with plain mockito instead.

  • Related