我是否应该期望由于Java即时编译,Mockito测试方法中没有的代码能够更快地运行?

问题描述

我需要一个小实验来帮助。我有两个测试文件

testFileA.javatestFileB.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魔术。