乐趣区

关于junit5:底层到底做了什么-junit5中ExtendWithParameterResolver的简单示例的执行过程

联合 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<Method> 里。(@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 办法,理论触发测试方法。
    到这里,就实现了整个测试方法的执行过程。
退出移动版