Springboot 测试高速化-1

最近突然发现,一个测试居然要30分钟才能跑完。记得最早的时候也就十几分钟。随着test case越来越多,时间就越来越长了。
要是按照这个增长幅度下去,明年估计跑完全部测试就要奔着1个小时去了。
网上查了一些资料,然后尝试了很多,最后总结出来这么几个有效的方案:

尽量不要在不同class里面定义MockBean

测试时最花费时间的,其实是启动DI环境,尤其是使用了spring的web模块,启动一次基本要一分半左右。如果像下面这样,在不同的class里定义MockBean的话,执行一个测试class,Spring就会认为context发生了变化,会去重启DI环境。

@RunWith(SpringRunner::class)
@SpringBootTest
@Transactional
abstract class BaseTest

class TestClassA: BaseTest() {
    @MockBean
    private lateinit var dateProvider: DateProvider
    
    @Test
    fun a() {
        assertNull(dateProvider.now())
    }
}

class TestClassB: BaseTest() {
    @MockBean
    private lateinit var dateProvider: DateProvider
    
    @Test
    fun a() {
        assertNull(dateProvider.now())
    }
}

像上面这种case,如果把MockBean定义到BaseTest里面,执行不同的TestClass,Spring也不会认为context发生了变化,只是会把数据rollback,而不会去重启DI环境。这样就能节省40%左右的时间。

@RunWith(SpringRunner::class)
@SpringBootTest
@Transactional
abstract class BaseTest {
    @MockBean
    protected lateinit var dateProvider: DateProvider
}

class TestClassA: BaseTest() {
    @Test
    fun a() {
        assertNull(dateProvider.now())
    }
}

class TestClassB: BaseTest() {
    @Test
    fun a() {
        assertNull(dateProvider.now())
    }
}

减少@SpringTest的使用

@SpringTest很方便,启动DI环境时会加载所有的Bean,但是同样也十分浪费时间,如果你只想测试Controller,Repository的话,可以使用@WebMvcTest或者@DataJpaTest等,这样可以减少加载的Bean的数目,提高DI环境的启动速度。

@Transactional
@RunWith(SpringRunner::class)
@DataJpaTest
@AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
abstract class DbTest

明确每一层的作用,写代码时注意不要跃层

Controller:仅作validation和转发
Repository:近作数据查询和更新操作
Service:业务逻辑
像这样把每层的责任范围都明确并严格执行。这样Controller的话基本就只写少量测试。然后Repository如果使用JPARepository的话,基本上只定义接口就可以,那么测试也比较少。重点基本都放到Service层了。
如果严格按照上面的功能划分,那么Service就可以独立出来一个模块。然后有使用Repository的case,@DataJpaTest基本上就可以cover大部分测试了。

尽量减少DI的使用

DI固然有很多好处,很方便。但是最好不要滥用。
同样的实装,如果不用DI,测试时就不用启动环境。速度就十分快了。
其实极端一点,放弃JPARepository,使用jooq,所有的数据访问都通过DSLContext去实现,那么就完全可以做过不启动DI环境进行绝大部分Service层的测试。
当然,是否采用这个策略要根据项目规模跟特点去判断。毕竟全都拿jooq写会增大代码量。对于小型web项目其实是不太适合的。

最后,记录下改善后的测试用时。隔个一年之后再回来看看,看那时测试用时会变成多久。

[INFO] bom ........................................ SUCCESS [  1.035 s]
[INFO] test ....................................... SUCCESS [ 21.486 s]
[INFO] domain-model ............................... SUCCESS [01:43 min]
[INFO] infrastructure ............................. SUCCESS [05:00 min]
[INFO] cms-web .................................... SUCCESS [05:47 min]
[INFO] series-web ................................. SUCCESS [04:36 min]
[INFO] batch ...................................... SUCCESS [02:44 min]

参考:
https://spring.pleiades.io/spring-boot/docs/2.1.11.RELEASE/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

Close Bitnami banner
Bitnami