Killer Beast
Killer Beast

Reputation: 499

Mocked class never always gives Null Pointer when running tests

I have a class that extends the CSRF repository of the Spring and where I have written a custom implementation. It looks somewhat like this:

public class CustomCookieCsrfTokenRepository implements CsrfTokenRepository {

    @Autowired
    JWKRepository jWKRepository;

    JWK jWK;

    @PostConstruct
    public void init() {
        jWK = jWKRepository.findGlobalJWK(null); // This is custom code, there will always be a valid object returned here
    }

    @Override
    public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {
        String tokenValue = token == null ? "" : token.getToken();
        log.info("JWK: " + jWK.getPrivateKey());
        // other logics
    }

}

And in my tests, I do something like this:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {CustomCookieCsrfTokenRepositoryTest.class, CustomCookieCsrfTokenRepositoryTest.TestConfig.class })
public class CustomCookieCsrfTokenRepositoryTest {

    @TestConfiguration
    static class TestConfig {
        @Bean
        CustomCookieCsrfTokenRepository customCookieCsrfTokenRepository() {
            return new CustomCookieCsrfTokenRepository();
        }
    }

    @Autowired
    CustomCookieCsrfTokenRepository customCookieCsrfTokenRepository;

    @MockBean
    HttpServletRequest request;

    @MockBean
    HttpServletResponse response;

    @MockBean
    RSAUtil rsaUtil;

    @MockBean
    JWKRepository jWKRepository;

    @MockBean
    JWK jWK;

    @Test
    public void saveToken() {
        CsrfToken csrfToken = customCookieCsrfTokenRepository.generateToken(request);
        String privateKey = "some key value";
        when(jWK.getPrivateKey()).thenReturn(privateKey);
        customCookieCsrfTokenRepository.saveToken(csrfToken, request, response);
        // some asserts
    }

}

So basically, the same token test case actually gets broken saying there is a NullPointer when I try to do jWK.getPrivateKey(). I tried to check if jWK is the null object but it isn't. I have verified by changing the log to print jWK object and it didn't throw any error. However, I am trying to mock and return the jWK object in my test case. Why doesn't this work? What's wrong with the above code? Any help will be appreciated.

Upvotes: 0

Views: 353

Answers (1)

Maciej Kowalski
Maciej Kowalski

Reputation: 26502

There are a few things here:

1) The JWK field is not an @Autowired field, thus @MockBean will not work on it. We need to use a simple @Mock on that field in the test.

2) In the @PostConstruct it is assigned based on the result of the jWKRepository.findGlobalJWK(null).

3) We need to mock that method:

@Before
private void init(){
   MockitoAnnotations.initMocks(this);
}    

@Mock
JWK jWK;

@Test
public void saveToken() {
    when(jWKRepository.findGlobalJWK(null)).thenReturn(jWK);
    ...
}

Upvotes: 2

Related Questions