认识自己的无知是认识世界最可靠的方法————互联网中的无名之辈
背景
公司最的海外项目临近上线,国内所有的环境都进行了单元测试,唯有海外环境还没进行,所以公司需要在海外环境进行单元测试。公司使用的是SpringBoot+TestNG写的单元测试,单元测试中去调用了其他微服务的Service。在国内环境只需要在本地或者jenkins上执行测试命令,比如通过mvn test 或者在IDEA里面直接执行对应的testng.mxl文件。
由于海外环境网络的限制和服务的限制公司需要将SpringBoot+TestNG打成jar包的形式去执行。不巧这个任务分配到我这了,我一听,哦,就是打个jar包跑测试啊,那岂不是洒洒水。
初探
坑1
我之前遇见的打包都是把单元测试排除的,现在的需求是将测试打包进去于是我就去网上找了找例子。嗯很快就找到了下面这篇博客.。
https://blog.csdn.net/qq_15290529/article/details/78989234
其实写的挺好的,我照做了之后发现问题来了,打包执行的时候需要有程序入口,现在的项目的有一个标准的SpringBoot Application入口,我想都没想就把它设置成了入口,不一会儿我的jar包就完成了。
后面我怀着不屑运行了java -jar 启动了程序,不出意外Application正常启动,等了等,嗯…嗯?不对劲,猛地意识到这个程序的入口有问题,入口应该设置成一个能启动所有TestNG测试的方法。
坑2
于是我开始思考怎么在Application启动的时候去执行单元测试呢?
不一会儿,我看了下面这篇博客之后有思路了.
http://www.voidcn.com/article/p-yehsfrxe-btn.html
我写了一个TestStartService 继承了ApplicationRunner,重写了run方法,我想的是这样能够在启动Application的时候执行单元测试。
@Component
@Order(value = 1)
public class TestStartService implements ApplicationRunner {
@Autowired
TestNG testNG;
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
List<String> suites = new ArrayList<String>();
suites.add("src/main/resources/testng.xml");
testNG.setTestSuites(suites);
testNG.run();
}
}
测试立马就报错了
Error starting ApplicationContext.
通过DEBUG发现确实是在容器启动的时候去加载了testng.xml,也去找了对应测试类,因为我们的测试类注入了其他系统的Service,但是这样的方式去执行测试的时候不会去加载上下文环境。我又去网上查了一波资料,看到 stackoverflow 上有个一样的需求,但是没人回答,我越来越觉得这个任务是个坑了。
https://stackoverflow.com/questions/63934534/how-to-create-fat-jar-with-tests-sources-and-all-dependencies-on-spring-boot-app
后来跑去读了SpringBoot官方文档、读了TestNG API文档、写了几个自己猜想的idea ,但是任还是失败告终。值得一提的是有一个类在我看到所以资料里面出现率非常高,我先留了个印象,先看看这个类,埋个伏笔。
org.testng.TestNG
最后的挣扎
这已经是第二天的事情了,昨日几乎找遍了全网有关TestNG的资料,尝试了我能想到的所有方法。距离任务结束就只有8小时左右了,作为刚刚入职的应届生(而且还没过试用期),我真的慌了,甚至都联想了卷包袱走人的场面。
现在该求的人都求了,该找的额资料都找了,唯有源码还没看,于是我就沉下心思看来看源码,因为上面提到的类出现频率最高,所以我就直接从这个类进去开始阅读源码。
org.testng.TestNG
看到下面这段代码我顿时沸腾了
public static void main(String[] argv) {
TestNG testng = privateMain(argv, (ITestListener)null);
System.exit(testng.getStatus());
}
@Deprecated
public void configure(Map cmdLineArgs) {
CommandLineArgs result = new CommandLineArgs();
Integer verbose = (Integer)cmdLineArgs.get("-log");
if (null != verbose) {
result.verbose = verbose;
}
result.outputDirectory = (String)cmdLineArgs.get("-d");
String testClasses = (String)cmdLineArgs.get("-testclass");
if (null != testClasses) {
result.testClass = testClasses;
}
String testNames = (String)cmdLineArgs.get("-testnames");
if (testNames != null) {
result.testNames = testNames;
}
String useDefaultListeners = (String)cmdLineArgs.get("-usedefaultlisteners");
if (null != useDefaultListeners) {
result.useDefaultListeners = useDefaultListeners;
}
result.groups = (String)cmdLineArgs.get("-groups");
result.excludedGroups = (String)cmdLineArgs.get("-excludegroups");
result.testJar = (String)cmdLineArgs.get("-testjar");
result.xmlPathInJar = (String)cmdLineArgs.get("-xmlpathinjar")