Java 模拟类在运行测试时从不总是给出空指针

Java 模拟类在运行测试时从不总是给出空指针,java,spring,unit-testing,junit,mockito,Java,Spring,Unit Testing,Junit,Mockito,我有一个类扩展了Spring的CSRF存储库,并在其中编写了一个自定义实现。看起来有点像这样: public class CustomCookieCsrfTokenRepository implements CsrfTokenRepository { @Autowired JWKRepository jWKRepository; JWK jWK; @PostConstruct public void init() { jWK = jW

我有一个类扩展了Spring的CSRF存储库,并在其中编写了一个自定义实现。看起来有点像这样:

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
    }

}
@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
    }

}
在我的测试中,我会这样做:

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
    }

}
@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
    }

}

因此,基本上,当我尝试执行
jWK.getPrivateKey()
时,同一个令牌测试用例实际上会被破坏,说有一个空指针。我试图检查
jWK
是否为空对象,但它不是。我已经通过将日志更改为print
jWK
对象进行了验证,它没有抛出任何错误。然而,我试图模拟并返回测试用例中的
jWK
对象。为什么这样不行?上面的代码有什么问题?任何帮助都将不胜感激。

这里有几点:

1)JWK字段不是一个
@Autowired
字段,因此
@MockBean
将无法在其上工作。我们需要在测试中对该字段使用一个简单的
@Mock

2)
@PostConstruct
中,它是根据
jWKRepository.findGlobalJWK(null)
的结果分配的

3)我们需要模仿这种方法:

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

@Mock
JWK jWK;

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

这里有几件事:

1)JWK字段不是一个
@Autowired
字段,因此
@MockBean
将无法在其上工作。我们需要在测试中对该字段使用一个简单的
@Mock

2)
@PostConstruct
中,它是根据
jWKRepository.findGlobalJWK(null)
的结果分配的

3)我们需要模仿这种方法:

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

@Mock
JWK jWK;

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

嗯,是的,你的方法是正确的。我不知道那些错误。但是,这并不能解决问题,我仍然在同一个位置获取null指针。jWK对象是否为null?或者它是模拟的?不确定它是否是模拟的,但它不是空的。我将log语句从
log.info(“JWK:+JWK.getPrivateKey())更改为
to
log.info(“JWK:+JWK”)并且它没有出现问题就通过了这一行。我尝试过的另一件事是在init本身内部返回mock jwk,但这也不起作用。在一个干净的建筑上,一切都很好。嗯,是的,你的方法是正确的。我不知道那些错误。但是,这并不能解决问题,我仍然在同一个位置获取null指针。jWK对象是否为null?或者它是模拟的?不确定它是否是模拟的,但它不是空的。我将log语句从
log.info(“JWK:+JWK.getPrivateKey())更改为
to
log.info(“JWK:+JWK”)并且它没有出现问题就通过了这一行。我尝试过的另一件事是在init本身内部返回mock jwk,但这也不起作用。在一个干净的建筑上,一切都很好。