《底层到底做了什么》--- junit5中@ExtendWith+ParameterResolver的简单示例的执行过程

结合github/junit5-samples-extensions简单说明@ExtendWith的底层执行流程。

代码

@ExtendWith(RandomParametersExtension.class)
class RandomParametersExtensionTests {
    @Test
    void injectsInteger(@Random int i, @Random int j) {
        assertNotEquals(i, j);
    }
}
public class RandomParametersExtension implements ParameterResolver {

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.PARAMETER)
    public @interface Random {
    }

    @Override
    public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
        return parameterContext.isAnnotated(Random.class);
    }

    @Override
    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
        return getRandomValue(parameterContext.getParameter(), extensionContext);
    }

    private Object getRandomValue(Parameter parameter, ExtensionContext extensionContext) {
        Class type = parameter.getType();
        java.util.Random random = extensionContext.getRoot().getStore(Namespace.GLOBAL)//
                .getOrComputeIfAbsent(java.util.Random.class);
        if (int.class.equals(type)) {
            return random.nextInt();
        }
        if (double.class.equals(type)) {
            return random.nextDouble();
        }
        throw new ParameterResolutionException("No random generator implemented for " + type);
    }

}

时序图
[图]

执行流程

  1. 在intellij里执行test
    1 如果是maven项目,执行intellij-rj里的一个main方法
    2 如果是gradle,是直接gradle的main方法。
  2. 调用junit-platform-launcher的入口。
  3. 创建NodeTestTask。
  4. 根据junit的配置,选择executorService,默认单线程,配置到NodeTestTask。
  5. 创建 ClassBasedTestDescriptor ,用来描述测试类RandomParametersExtensionTests。
  6. ClassBasedTestDescriptor调用prepare方法,扫描测试类、参数、方法上所有的注解,比如类的@extendWith,方法上的@BeforeALl等。@extendWith修饰的extendsion放到extendsionRegistry,@BeforeALl修饰的单独放到对应List里。(@extendWith是junit预留的扩张类入口)
    到这里,就完成了注解的扫描。
  7. 创建TestMethodTestDescriptor,用来描述测试方法 injectsInteger()
  8. TestMethodTestDescriptor调用execute方法,依次触发@BeforeEach等描述的方法,然后调用实际的invokeMethod,然后再出发@BeforeAfter等描述的方法。
  9. invokeMethod方法,先调用resolveParameters方法

    1. 扫描extendsionRegistry里的实现ParameterReslolver接口的extendsion,这里就是RandomParametersExtension类。(ParameterReslolver接口是junit预留的参数解析的入口
    2. RandomParametersExtension调用resolveParameters方法

      1. 先调用supportParameter,检查method是否支持这个Extension,这里是通过参数上@Random判断。
      2. 调用resolveParameter,设置方法的argument。

    到这里,就完成了参数的解析。

  10. invokeMethod方法,实际调用invke方法,通过reflect调用native方法,实际触发测试方法。
    到这里,就完成了整个测试方法的执行过程。

你可能感兴趣的:(《底层到底做了什么》--- junit5中@ExtendWith+ParameterResolver的简单示例的执行过程)