一起单测引起的项目加载失败惨案
作者:京东科技 宋慧超
一、前言
最近在开发一个功能模块时,在功能自测阶段,通过使用单测测试功能的完整性,在测试单测联通性使用到静态方法测试时,发现单测报错,通过查阅解决方案发现需要对Javaassist包进行排包或者升版本处理。通过排包解决掉单测报错,在部署项目时发现频繁报bean注入失败问题,最终定位发现是因为对Javaassist包排包引起的bean加载失败。故而对Javaassist包相关知识进行学习整理文章如下。
单测相关报错信息如下:
Powermock - java.lang.IllegalStateException: Failed to transform class
解决单测报错的文章链接:
二、问题复现
1、前期准备
首先使用了Spring框架新建一个demo,并写一个简单测试类对问题进行复现。
UserService
的定义:
public interface UserService {
void save(User user);
}
UserServiceImpl
的实现代码:
@Service
public class UserServiceImpl implements UserService {
private UserDao userDao;
@Autowired
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save(User user) {
userDao.save(user);
}
}
这里我们使用了Spring框架的@Service
和@Autowired
注解,以便让Spring框架自动装配UserDao
实例。
但是,在我们的POM文件中,虽然我们添加了对Spring框架的依赖,但是并没有添加Javaassist库的依赖。而UserServiceImpl
中确实使用了Javaassist库来进行字节码操作, UserServiceImpl
的具体实现代码:
public class UserServiceImpl implements UserService {
// ...
private static final String USER_CLASS_NAME = "com.example.User";
private static final Class<?> USER_CLASS;
static {
try {
USER_CLASS = Class.forName(USER_CLASS_NAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public void save(User user) {
try {
// 创建一个ClassPool对象
ClassPool cp = ClassPool.getDefault();
// 从ClassPool中获取一个CtClass对象
CtClass ctClass = cp.get(USER_CLASS_NAME)