背景
需要测试不同版本的mysql jdbc jar包连接mysql代理的一个兼容性.比如有下列的驱动版本,需要进行兼容性测试.手动一个一个进行测试的话,效率太低,所以需要实现一种自动化测试方法.
mysql-connector-j-8.0.31.jar
mysql-connector-j-8.0.32.jar
mysql-connector-java-3.1.14.jar
mysql-connector-java-5.1.4.jar
mysql-connector-java-5.1.49.jar
mysql-connector-java-8.0.11.jar
mysql-connector-java-8.0.12.jar
mysql-connector-java-8.0.13.jar
mysql-connector-java-8.0.14.jar
mysql-connector-java-8.0.15.jar
mysql-connector-java-8.0.16.jar
mysql-connector-java-8.0.17.jar
mysql-connector-java-8.0.18.jar
mysql-connector-java-8.0.19.jar
mysql-connector-java-8.0.20.jar
mysql-connector-java-8.0.21.jar
mysql-connector-java-8.0.22.jar
mysql-connector-java-8.0.23.jar
mysql-connector-java-8.0.24.jar
mysql-connector-java-8.0.25.jar
mysql-connector-java-8.0.26.jar
mysql-connector-java-8.0.27.jar
mysql-connector-java-8.0.28.jar
mysql-connector-java-8.0.29.jar
mysql-connector-java-8.0.30.jar
自动化实现
1. 用到的maven依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.18</version>
</dependency>
2. 自定义类加载器
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@Slf4j
public class ConnectorClassLoader extends ClassLoader {
private final JarFile jarFile;
Map<String, Class<?>> loadedClassesMap = new HashMap<>();
public ConnectorClassLoader(String jarPath) throws IOException {
jarFile = new JarFile(jarPath);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> clazz = loadedClassesMap.get(name);
if (clazz != null) {
return clazz;
}
try {
if (name.startsWith("com.mysql.")) {
final byte[] bytes = findJarClass(name);
clazz = defineClass(name, bytes, 0, bytes.length);
}
} catch (Exception e) {
//e.printStackTrace();
clazz = findClass(name);
}
if (clazz != null) {
loadedClassesMap.put(name, clazz);
return clazz;
}
return super.loadClass(name);
}
private byte[] findJarClass(String className) throws IOException {
String tmp = className.replaceAll("\\.", "/");
JarEntry entry = jarFile.getJarEntry(tmp + ".class");
if (entry == null) {
log.info(className);
return null;
}
InputStream inputStream = jarFile.getInputStream(entry);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int next = inputStream.read();
while (-1 != next) {
outputStream.write(next);
next = inputStream.read();
}
return outputStream.toByteArray();
}
}
3. 自动化测试
mysql jdbc jar包在目录 E:\\java\\workspace\\autotest\\ext-libs\\connector-libs 下面
import cn.hutool.core.util.ReUtil;
import cn.hutool.db.Entity;
import cn.hutool.db.handler.EntityListHandler;
import cn.hutool.db.sql.SqlExecutor;
import com.olym.autotest.config.TableConfig;
import com.olym.autotest.test.testcases.dbencdec.connector.ConnectorClassLoader;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
@Slf4j
public class MysqlJdbcDifferentVersionTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException, InstantiationException, IllegalAccessException, IOException {
String jdbcUrl = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false&useOldAliasMetadataBehavior=false";
String driverClassName;
Properties properties = new Properties();
properties.put("user", "root");
properties.put("password", "123456");
String jarsDir = "E:\\java\\workspace\\autotest\\ext-libs\\connector-libs";
List<File> jdbcJarList = cn.hutool.core.io.FileUtil.loopFiles(new File(jarsDir), file -> {
if (file.getName().endsWith(".jar")) {
return true;
}
return false;
});
for (File file : jdbcJarList) {
log.info("jar包名称: {}", file.getName());
boolean match = ReUtil.isMatch("mysql-connector-.*-[1-9]\\.[0-9]+\\.[0-9]+\\.jar", file.getName());
if(!match) {
continue;
}
boolean match8 = ReUtil.isMatch("mysql-connector-.*-[8-9]\\.[0-9]+\\.[0-9]+\\.jar", file.getName());
if(!match8) {
driverClassName = "com.mysql.jdbc.Driver";
}else{
driverClassName = "com.mysql.cj.jdbc.Driver";
}
ConnectorClassLoader classLoader = new ConnectorClassLoader(jarsDir + File.separator + file.getName());
Driver driver = (Driver)classLoader.loadClass(driverClassName).newInstance();
log.info("大版本: {}, 小版本: {}", driver.getMajorVersion(), driver.getMinorVersion());
Connection connection = driver.connect(jdbcUrl, properties);
List<Entity> queryResult = SqlExecutor.query(connection, "select * from test.test_table", new EntityListHandler());
log.info(queryResult.toString());
}
}
}
4. 遇到的问题
- MissingResourceException异常
当遍历到 mysql-connector-java-5.1.4.jar的时候抛出下面的异常
Caused by: java.lang.RuntimeException: Can't load resource bundle due to underlying exception java.util.MissingResourceException: Can't find bundle for base name com.mysql.jdbc.LocalizedErrorMessages, locale zh_CN
at com.mysql.jdbc.Messages.<clinit>(Messages.java:60)
... 5 more
在idea工程中,右键E:\\java\\workspace\\autotest\\ext-libs\\connector-libs目录,添加为库即可.