问题描述
testFileA.java
和testFileB.java
testFileA.java
看起来
@Test
public void test1() throws Throwable {
Instant start = Instant.Now();
mvc.perform(mockmvcRequestBuilders
.post('someEndpoint/')
.andDo(print())
.andExpect(status().isCreated())
Instant end = Instant.Now();
System.out.println(">>>>>>>>>>>>>>>>>End" + Duration.between(start,end));
}
@Test
public void test2() throws Throwable {
//same contents as test 1
}
@Test
public void test3() throws Throwable {
//same contents as test 1
}
testFileB.java
看起来
@Test
public void test1() throws Throwable {
Instant start = Instant.Now();
this.abstractedCode();
Instant end = Instant.Now();
System.out.println(">>>>>>>>>>>>>>>>>End" + Duration.between(start,end));
}
@Test
public void test2() throws Throwable {
//same contents as test 1
}
@Test
public void test3() throws Throwable {
//same contents as test 1
}
public void abstractedCode(){
mvc.perform(mockmvcRequestBuilders
.post('someEndpoint/')
.andDo(print())
.andExpect(status().isCreated())
}
我对testFileB.java
的期望是,第一个测试将花费更长的时间,然后每个后续的测试将不花那么长时间,因为重复的代码被重构为方法调用; Java JIT编译器做到了这一点,因此我们不必再次重新编译相同的代码。事实证明我的期望是正确的。
我对testFileA.java
的期望是,每个测试将花费与上一个测试一样长的时间,因为通用代码没有被重构为一个函数,但是最终却不成立。行为是相同的,第一次测试花费了更长的时间,然后接下来的两次则缩短了。
我猜想JVM内正在发生某些事情,因此我调用的mvc.perform()
方法不必一次又一次地重新编译,JIT编译器正在帮助我的程序尽管它不在我定义的函数中。是真的吗?
解决方法
一个独特的非答案:您将时间浪费在了错误的地方。
“ JIT优化”的收益仅在应用程序运行很长一段时间,调用相同方法数百万次的设置中才有意义。
JIT的目的不是优化在JVM的生存期内一次调用的测试方法。
含义:花费您的时间来训练如何编写可测试的生产代码以及清理测试代码。这在这里更重要。
当然:单元测试套件的执行时间仍然很重要。但是,当这变成一个问题时,您很可能会遇到编写不佳的测试,例如使用默认超时和诸如此类...最终导致测试耗时数秒(如果不是数分钟)。那是你所关心的。尽管对于单元测试环境,您绝对不关心JIT魔术。