3

Java非Spring框架下的单元测试

 2 years ago
source link: https://my.oschina.net/cuttese/blog/5123677
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

当下的大部分的Java项目都是基于Spring框架的,这固然带来了很大的便利,但是也引入了一些其他的问题。例如在对Service、Component进行单元测试的时候,虽然Junit等测试框架提供了相关框架的支持,但是如果是一个有点儿历史的、封装并不是很很合理的、方法类的单一职责做的不好的项目,进行一次单元测试,框架启动耗时30秒,测试方法5ms。时间举例有些极端,但这也是目前很多项目真实面临的情况。

如何脱离框架支持,直接进行单元测试

脱离框架的支持,直接进行单元测试,面临的第一个较大的问题就是“依赖”如何解决。Spring及Spring-boot框架解决的一个大问题就是依赖管理的问题,其提供的依赖注入和自动装配确实提供了很大的便利性,但在单元测试进行时最大的阻力就是这些依赖如何注入的问题。有框架支持的情况下可以从bean容器中拿来即用,但若是脱离了框架就需要手动进行初始化。

测试需求介绍
  1. 本次需要对ClassA的aMethod方法进行单元测试,这是一个有一个入参:TestParam,和一个返回值:Result的方法。
  2. 在ClassA的Amethod方法中,分别调用了ClassB的bMethod方法和ClassC的cMethod方法。
实现关键内容简介说明
  1. 被测试对象ClassA直接new出来一个真实的对象,里面的各种以来肯定是没有注入的。
  2. 对与被依赖的对象ClassB和ClassC,使用Mockito.mock(Class clazz)方法构建模拟对象出来。
  3. 使用反射将模拟对象clazzB和clazzC手动注入到被测试对象clazzA中。
  4. 使用Mockito的各种方法,对clazzB和clazzC进行加强。
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

import java.lang.reflect.Field;

// 指定运行器纯属个人习惯,使用默认的也可
@RunWith(MockitoJUnitRunner.class)
public class ClassATest {

    private final ClassA clazzA = new ClassA();
    private final ClassB clazzB = Mockito.mock(ClassB.class);
    private final ClassC clazzC = Mockito.mock(ClassC.class);

    @Test
    public void onceTest() throws IllegalAccessException {
        // 将需要的对象注入被测试对象
        Field[] declaredFields = ClassA.class.getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            if (field.getName().equals("classA")) {
                field.set(tradeOrderStore, orderNoUtil);
            } else if (field.getName().equals("clazzB")) {
                field.set(tradeOrderStore, tradeProductUtil);
            }
        }
        //打桩、模拟
        Mockito.when(clazzB.bMethod(Mockito.any())).thenReturn("MC" + new Random().nextInt(1999999999));
        Mockito.when(clazzC.bMethod(Mockito.anyInt())).thenReturn(Boolean.TRUE);
        // 构建测试方法的入参
        TestParam tp = new TestParam();
        // 为测试入参设置测试值的代码省略......
        // 使用测试入参,执行测试方法
        Result testResult = clazzA.aMethod(tp);
        Assert.assertNotNull(testResult);
        // 其他测试验证省略......
    }
}

通过以上,就可以脱离框架执行进行单元测试了,此时单元测试的运行执行就大大降低了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK