修改密码为EncryptedPassword引用类型后Java单元测试报空指针异常
问题根因
你遇到的空指针异常来自EncryptedPassword类的decrypt()方法,核心原因是手动new出来的EncryptedPassword实例不会被Spring完成依赖注入,类内标注@Autowired的passwordUtil属性为null,调用passwordUtil.convert时触发空指针。
排查步骤
- 给单元测试加完整异常栈打印:在
client.getItems()外层添加try-catch捕获异常,打印完整栈轨迹,可直接定位到异常抛出的具体代码行 - 断点调试:在
EncryptedPassword的构造方法、decrypt方法分别打断点,运行测试即可直观看到passwordUtil属性为null,直接确认问题点
解决方案
方案1:改造EncryptedPassword,放弃依赖注入
把EncryptedPassword改造成普通POJO,依赖通过参数传入即可,适合不需要Spring管理的场景:
public class EncryptedPassword { private String encryptedPass; public EncryptedPassword (String encryptedString) { encryptedPass = encryptedString; } // PasswordUtil作为参数传入方法 public String decrypt(PasswordUtil passwordUtil) { return new String(passwordUtil.convert(new Base64().decode(encryptedPass)), Charsets.UTF_8); } }
后续调用decrypt时,传入Spring容器中已初始化完成的PasswordUtil实例即可。
方案2:把EncryptedPassword交给Spring容器管理
如果需要保留@Autowired注入逻辑,就不要手动调用构造方法new实例,通过Spring上下文获取Bean:
- 给
EncryptedPassword类上加@Component注解,标注为Spring管理的Bean - 单元测试引入Spring Test支持,直接注入Bean使用,改造示例:
@SpringBootTest public class MenuRestClientTest { private static String host; private static String user; private static String pass; @Autowired private EncryptedPassword encryptedPassword; @BeforeAll public static void setup() { host = "host"; user = "user"; pass = "test123"; } @Test void queryNumberOfItems() throws Exception { // 给EncryptedPassword补充setEncryptedPass方法后设置属性 encryptedPassword.setEncryptedPass(pass); MenuRestClient client = new MenuRestClient(host).credentials(user, encryptedPassword); final int items = client.getItems(); logger.info("Found {} items", items); } }
方案3:单元测试Mock依赖
仅单元测试场景下可以用Mock工具绕过依赖注入问题,示例:
@Test void queryNumberOfItems() throws Exception { EncryptedPassword password = new EncryptedPassword(pass); // Mock PasswordUtil实例 PasswordUtil mockUtil = Mockito.mock(PasswordUtil.class); Mockito.when(mockUtil.convert(Base64.decodeBase64(pass))).thenReturn("test123".getBytes(Charsets.UTF_8)); // 反射给password注入mock的util ReflectionTestUtils.setField(password, "passwordUtil", mockUtil); MenuRestClient client = new MenuRestClient(host).credentials(user, password); final int items = client.getItems(); logger.info("Found {} items", items); }
内容的提问来源于stack exchange,提问作者BNK
相关产品推荐
相关产品推荐

