添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  • 代码组织:为了避免在开发或调试过程中浪费时间,有必要将单元测试从集成测试中区分出来。
  • 依赖框架:根据定义,单元测试不需要运行任何框架容器(JDK和JUnit应该足够),集成测试需要运行时所需的所有框架,这极大增加了编译时间。
  • 依赖环境:集成测试依赖外部工具(数据库,外部API等),从集成测试中拆分单元可以使编译时间更短,并尽可能快地运行测试。
  • 拆分单元测试与集成测试

    单元测试 Mock

    使用 Mock 框架 Mockito、Powermock。

    // 依赖管理
    testCompile group: 'org.mockito', name: 'mockito-core', version: '3.1.0'
    testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.4'
    testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.4'
    

    Mockito 框架初始化

    // 通过注解的方式初始化Mockito环境
    @Before
    public void before() {
        MockitoAnnotations.initMocks(this);
    // 通过编码的方式初始化Mockito环境
    @RunWith(MockitoJUnit44Runner.class)  
    public class ExampleTest {}
    

    Mock void方法

    对于 void 返回值的方法,一般可不用去 mock 它,只需用 verify() 去验证,或者模拟出现异常时的情况。

    doNothing().when(mockObject).methodWithVoidReturn();
    doThrow(new RuntimeException()).when(mockObject).methodWithVoidReturn();
    

    Mock Spring注解

    由于@PostConstruct是专属于Spring框架的概念,只能手工调用。

    @Before
    public void prepare() {
        MockitoAnnotations.initMocks(this);
        this.service.init(); //your Injected bean
    

    Mock成员变量

    1、使用 PowerMock 提供的 Whitebox Mock成员变量

    Whitebox.setInternalState(underTest, "person", mockedPerson);
    

    2、Apache Commons Lang:这是Apache软件基金会开发的一个常用工具库,其中包含许多常用的Java工具类。其中有一个名为FieldUtils的类,可以使用它来设置静态变量。

    public class YourClass {
        private final int finalField = 42;
        public int getFinalField() {
            return finalField;
    public class YourClassTest {
        @Test
        public void testFinalFieldModification() throws Exception {
            YourClass obj = new YourClass();
            Field field = FieldUtils.getField(YourClass.class, "finalField", true);
            FieldUtils.removeFinalModifier(field, true);
            FieldUtils.writeField(field, obj, 100, true);
            assertEquals(100, obj.getFinalField());
    

    Mock静态方法

    1、使用Powermock框架,Powermock在Mockito框架的基础上,支持Mock静态方法。

    @Slf4j
    @RunWith(PowerMockRunner.class)
    @PowerMockIgnore("javax.net.ssl.*")
    @PrepareForTest({ DriverManager.class })
    public class Mocker {
      @Test
      public void shouldVerifyParameters() throws Exception {
          //given
          PowerMockito.mockStatic(DriverManager.class);
          BDDMockito.given(DriverManager.getConnection(...)).willReturn(...);
          //when
          sut.execute(); // System Under Test (sut)
          //then
          PowerMockito.verifyStatic();
          DriverManager.getConnection(...);
    

    2、使用 Mockito Mock 静态方法

    try (MockedStatic<IpUtils> ipUtilsMockedStatic = Mockito.mockStatic(IpUtils.class)) {
        ipUtilsMockedStatic.when(IpUtils::getClientIpAddress).thenReturn("127.0.0.1");
    

    用例的执行顺序

    JUnit是通过@FixMethodOrder注解来控制测试方法的执行顺序的。@FixMethodOrder注解的参数是org.junit.runners.MethodSorters对象在枚举类org.junit.runners.MethodSorters中定义了如下三种顺序类型:

    MethodSorters.DEFAULT(默认的顺序,以确定但不可预期的顺序执行)

    Sorts the test methods in a deterministic, but not predictable, order.

    MethodSorters.JVM(按照JVM得到的方法顺序,也就是代码中定义的方法顺序)

    Leaves the test methods in the order returned by the JVM. Note that the order from the JVM may vary from run to run.

    MethodSorters.NAME_ASCENDING(按方法名字母顺序执行)

    Sorts the test methods by the method name, in lexicographic order, with Method.toString() used as a tiebreaker.

    单测的超时时间

    问题:为什么要关注测试用例的执行的超时时间?

    由于在做自动化持续集成的时候,发现很多项目的集成测试用例由于环境问题,导致执行的时候无限调用等待的情况,最终导致持续集成在跑集成用例的环节卡死,占用资源而无法释放需要人工介入处理。

    在编写单元测试的时候,设定单元测试与集成测试的超时时间。

    // 设置所有方法执行的超时时间
    @ClassRule
    public static Timeout globalTimeout = Timeout.seconds(30);
    // 设置每个方法执行的超时时间
    @Rule
    public Timeout methodTimeout = Timeout.seconds(30);
    

    单元测试覆盖率

  • jacoco
  • SpringRunner继承自SpringJUnit4ClassRunner,其只是SpringJUnit4ClassRunner的一个别名类。

    JUnit的测试用例总是由Runner去执行,JUnit提供@RunWith注解用于指定Runner,如果未指定特别的Runner,那么会采用默认的Runner。 因此,@RunWith(SpringJUnit4ClassRunner.class)是由Spring定义的Runner,用于加载Spring的配置文件以及与Spring相关的事物。

    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class ApplicationTest {}
    

    那么自定义的Runner有什么用呢?它可以截获到@BeforeClass, @AfterClass, @Before, @After这些事件,也就是能在测试类开始和结束执行前后,每个测试方法的执行前后处理点事情。

    编写JUnit4自定义Runner

  • https://blog.worldline.tech/2020/04/10/split-unit-and-integration-tests.html
  • https://yanbin.blog/extend-junit-4-customized-runner/
  •