下面列出了org.junit.jupiter.api.extension.ExtensionConfigurationException#org.junit.jupiter.api.extension.ExtensionContext.Store 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Create {@link Injector} or get existing one from test context
*/
private static Optional<Injector> getOrCreateInjector(ExtensionContext context)
throws NoSuchMethodException, InstantiationException, IllegalAccessException,
InvocationTargetException {
Optional<AnnotatedElement> optionalAnnotatedElement = context.getElement();
if (!optionalAnnotatedElement.isPresent()) {
return Optional.empty();
}
AnnotatedElement element = optionalAnnotatedElement.get();
Store store = context.getStore(NAMESPACE);
Injector injector = store.get(element, Injector.class);
if (injector == null) {
injector = createInjector(context);
store.put(element, injector);
}
return Optional.of(injector);
}
@Override
public void beforeAll(ExtensionContext context) {
Class<?> testClass = context.getTestClass()
.orElseThrow(() -> new ExtensionConfigurationException("TestcontainersExtension is only supported for classes."));
Store store = context.getStore(NAMESPACE);
List<StoreAdapter> sharedContainersStoreAdapters = findSharedContainers(testClass);
sharedContainersStoreAdapters.forEach(adapter -> store.getOrComputeIfAbsent(adapter.getKey(), k -> adapter.start()));
List<TestLifecycleAware> lifecycleAwareContainers = sharedContainersStoreAdapters
.stream()
.filter(this::isTestLifecycleAware)
.map(lifecycleAwareAdapter -> (TestLifecycleAware) lifecycleAwareAdapter.container)
.collect(toList());
store.put(SHARED_LIFECYCLE_AWARE_CONTAINERS, lifecycleAwareContainers);
signalBeforeTestToContainers(lifecycleAwareContainers, testDescriptionFrom(context));
}
@Override
public void beforeEach(ExtensionContext context) {
IdeaMocksImpl ideaMocks = new IdeaMocksImpl();
Project project = mock(Project.class);
MessageBus messageBus = mock(MessageBus.class);
when(project.getMessageBus()).thenReturn(messageBus);
when(messageBus.syncPublisher(any(Topic.class))).thenAnswer(invocation -> {
Topic topic = invocation.getArgument(0);
Class<?> listenerClass = topic.getListenerClass();
if (ideaMocks.hasMockListener(listenerClass)) {
return ideaMocks.getMockListener(listenerClass);
} else {
return ideaMocks.mockListener(listenerClass);
}
});
Store store = context.getStore(NS);
ParameterHolder holder = ParameterHolder.getHolder(store);
holder.register(Project.class, Suppliers.ofInstance(project));
holder.register(MessageBus.class, Suppliers.ofInstance(messageBus));
holder.register(IdeaMocks.class, Suppliers.ofInstance(ideaMocks));
}
/**
* Get the {@link TestContextManager} associated with the supplied {@code ExtensionContext}.
* @return the {@code TestContextManager} (never {@code null})
*/
private static TestContextManager getTestContextManager(ExtensionContext context) {
Assert.notNull(context, "ExtensionContext must not be null");
Class<?> testClass = context.getRequiredTestClass();
Store store = getStore(context);
return store.getOrComputeIfAbsent(testClass, TestContextManager::new, TestContextManager.class);
}
private ExtensionContext buildExtensionContext(String methodName) {
Class<?> testClass = SpringTestCase.class;
Method method = ReflectionUtils.findMethod(getClass(), methodName);
Store store = mock(Store.class);
given(store.getOrComputeIfAbsent(any(), any(), any())).willReturn(new TestContextManager(testClass));
ExtensionContext extensionContext = mock(ExtensionContext.class);
given(extensionContext.getTestClass()).willReturn(Optional.of(testClass));
given(extensionContext.getElement()).willReturn(Optional.of(method));
given(extensionContext.getStore(any())).willReturn(store);
return extensionContext;
}
/**
* Get the {@link TestContextManager} associated with the supplied {@code ExtensionContext}.
* @return the {@code TestContextManager} (never {@code null})
*/
private static TestContextManager getTestContextManager(ExtensionContext context) {
Assert.notNull(context, "ExtensionContext must not be null");
Class<?> testClass = context.getRequiredTestClass();
Store store = getStore(context);
return store.getOrComputeIfAbsent(testClass, TestContextManager::new, TestContextManager.class);
}
private ExtensionContext buildExtensionContext(String methodName) {
Class<?> testClass = SpringTestCase.class;
Method method = ReflectionUtils.findMethod(getClass(), methodName);
Store store = mock(Store.class);
when(store.getOrComputeIfAbsent(any(), any(), any())).thenReturn(new TestContextManager(testClass));
ExtensionContext extensionContext = mock(ExtensionContext.class);
when(extensionContext.getTestClass()).thenReturn(Optional.of(testClass));
when(extensionContext.getElement()).thenReturn(Optional.of(method));
when(extensionContext.getStore(any())).thenReturn(store);
return extensionContext;
}
private Object getMock(Parameter parameter, ExtensionContext extensionContext) {
Class<?> mockType = parameter.getType();
Store mocks = extensionContext.getStore(Namespace.create(MockitoExtension.class, mockType));
String mockName = getMockName(parameter);
if (mockName != null) {
return mocks.getOrComputeIfAbsent(mockName, key -> mock(mockType, mockName));
}
else {
return mocks.getOrComputeIfAbsent(mockType.getCanonicalName(), key -> mock(mockType));
}
}
private Object getMock(Parameter parameter, ExtensionContext extensionContext) {
Class<?> mockType = parameter.getType();
Store mocks = extensionContext.getStore(Namespace.create(MockitoExtension.class, mockType));
String mockName = getMockName(parameter);
if (mockName != null) {
return mocks.getOrComputeIfAbsent(mockName, key -> mock(mockType, mockName));
} else {
return mocks.getOrComputeIfAbsent(mockType.getCanonicalName(), key -> mock(mockType));
}
}
@Override
public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(
ExtensionContext context) {
List<WithAccessId> accessIds =
AnnotationSupport.findRepeatableAnnotations(context.getElement(), WithAccessId.class);
Store store = getStore(context);
return accessIds.stream()
.peek(a -> store.put(ACCESS_IDS_STORE_KEY, a))
.map(JaasExtensionInvocationContext::new);
}
/**
* Returns an injector for the given context if and only if the given context has an {@link
* ExtensionContext#getElement() annotated element}.
*/
private static Optional<Injector> getOrCreateInjector(ExtensionContext context)
throws NoSuchMethodException,
InstantiationException,
IllegalAccessException,
InvocationTargetException {
if (!context.getElement().isPresent()) {
return Optional.empty();
}
AnnotatedElement element = context.getElement().get();
Store store = context.getStore(NAMESPACE);
Injector injector = store.get(element, Injector.class);
boolean sharedInjector = isSharedInjector(context);
Set<Class<? extends Module>> moduleClasses = Collections.emptySet();
if (injector == null && sharedInjector) {
moduleClasses = getContextModuleTypes(context);
injector = INJECTOR_CACHE.get(moduleClasses);
}
if (injector == null) {
injector = createInjector(context);
store.put(element, injector);
if (sharedInjector && !moduleClasses.isEmpty()) {
INJECTOR_CACHE.put(moduleClasses, injector);
}
}
return Optional.of(injector);
}
private Object getMock(Parameter parameter,
ExtensionContext extensionContext) {
Class<?> mockType = parameter.getType();
Store mocks = extensionContext
.getStore(Namespace.create(MockitoExtension.class, mockType));
String mockName = getMockName(parameter);
if (mockName != null) {
return mocks.getOrComputeIfAbsent(mockName,
key -> mock(mockType, mockName));
} else {
return mocks.getOrComputeIfAbsent(mockType.getCanonicalName(),
key -> mock(mockType));
}
}
private Object getMock(Parameter parameter,
ExtensionContext extensionContext) {
Class<?> mockType = parameter.getType();
Store mocks = extensionContext
.getStore(Namespace.create(MockitoExtension.class, mockType));
String mockName = getMockName(parameter);
if (mockName != null) {
return mocks.getOrComputeIfAbsent(mockName,
key -> mock(mockType, mockName));
} else {
return mocks.getOrComputeIfAbsent(mockType.getCanonicalName(),
key -> mock(mockType));
}
}
private Object getMock(Parameter parameter, ExtensionContext extensionContext) {
Class<?> mockType = parameter.getType();
Store mocks = extensionContext.getStore(Namespace.create(MockitoExtension.class, mockType));
String mockName = getMockName(parameter);
if (mockName != null) {
return mocks.getOrComputeIfAbsent(mockName, key -> mock(mockType, mockName));
}
else {
return mocks.getOrComputeIfAbsent(mockType.getCanonicalName(), key -> mock(mockType));
}
}
private boolean isSpringTestContextEnabled(ExtensionContext extensionContext) {
if (!extensionContext.getTestClass().isPresent()) {
return false;
}
Store springStore = extensionContext.getRoot().getStore(Namespace.create(SpringExtension.class));
return springStore != null && springStore.get(extensionContext.getTestClass().get()) != null;
}
private static Optional<io.micronaut.context.ApplicationContext> getMicronautApplicationContext(ExtensionContext extensionContext) {
Store micronautStore = extensionContext.getRoot().getStore(Namespace.create(MicronautJunit5Extension.class));
if (micronautStore != null) {
try {
io.micronaut.context.ApplicationContext appContext = (io.micronaut.context.ApplicationContext) micronautStore.get(io.micronaut.context.ApplicationContext.class);
if (appContext != null) {
return Optional.of(appContext);
}
} catch (ClassCastException ex) {
}
}
return Optional.empty();
}
@Override
public void beforeEach(final ExtensionContext context) {
Store store = context.getStore(NAMESPACE);
List<TestLifecycleAware> lifecycleAwareContainers = collectParentTestInstances(context).parallelStream()
.flatMap(this::findRestartContainers)
.peek(adapter -> store.getOrComputeIfAbsent(adapter.getKey(), k -> adapter.start()))
.filter(this::isTestLifecycleAware)
.map(lifecycleAwareAdapter -> (TestLifecycleAware) lifecycleAwareAdapter.container)
.collect(toList());
store.put(LOCAL_LIFECYCLE_AWARE_CONTAINERS, lifecycleAwareContainers);
signalBeforeTestToContainers(lifecycleAwareContainers, testDescriptionFrom(context));
}
/**
* Get the {@link TestContextManager} associated with the supplied {@code ExtensionContext}.
* @return the {@code TestContextManager} (never {@code null})
*/
private static TestContextManager getTestContextManager(ExtensionContext context) {
Assert.notNull(context, "ExtensionContext must not be null");
Class<?> testClass = context.getRequiredTestClass();
Store store = getStore(context);
return store.getOrComputeIfAbsent(testClass, TestContextManager::new, TestContextManager.class);
}
@Override
public void afterEach(ExtensionContext context) throws Exception {
Store store = getStore(context);
try {
closeTemporaryOut(store);
}
finally {
restoreSystemOutAndClearStore(store);
}
}
/**
* Override {@code System.out} stream with custom out stream.
*
* @param store The extension store.
*/
private static void overrideSystemOut(Store store) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream outStream = new PrintStream(out);
System.setOut(outStream);
store.put(TEMPORARY_OUT_STORE_KEY, out);
}
/**
* Restore {@code System.out} stream and clear extension store (even if an error
* occurred while restoring stream).
*
* @param store The extension store.
*/
private static void restoreSystemOutAndClearStore(Store store) {
try {
restoreSystemOut(store);
}
finally {
clearStore(store);
}
}
@Override
public void afterEach(ExtensionContext context) {
Store store = getStore(context);
WireMockServer wireMockServer = store.get(STORE_KEY, WireMockServer.class);
try {
wireMockServer.stop();
}
finally {
store.remove(STORE_KEY);
}
}
/**
* Retrieves the test data from given dataprovider method.
*
* @param dataProviderMethod the dataprovider method that gives the parameters; never {@code null}
* @param cacheDataProviderResult determines if the dataprovider result should be cached using
* {@code dataProviderMethod} as key
* @param context the execution context to use to create a {@link TestInfo} if required; never {@code null}
*
* @return a list of methods, each method bound to a parameter combination returned by the dataprovider
* @throws NullPointerException if and only if one of the given arguments is {@code null}
*/
protected Object invokeDataProviderMethodToRetrieveData(Method dataProviderMethod, boolean cacheDataProviderResult,
ExtensionContext context) {
checkNotNull(dataProviderMethod, "'dataProviderMethod' must not be null");
checkNotNull(context, "'context' must not be null");
Store store = context.getRoot().getStore(NAMESPACE_USE_DATAPROVIDER);
Object cached = store.get(dataProviderMethod);
if (cached != null) {
return cached;
}
try {
// TODO how to not require junit-jupiter-engine dependency and reuse already existing ExtensionRegistry?
ExtensionRegistry extensionRegistry = createRegistryWithDefaultExtensions(
new DefaultJupiterConfiguration(emptyConfigurationParameters()));
Object data = executableInvoker.invoke(dataProviderMethod, context.getTestInstance().orElse(null), context,
extensionRegistry, InvocationInterceptor::interceptTestFactoryMethod);
if (cacheDataProviderResult) {
store.put(dataProviderMethod, data);
}
return data;
} catch (Exception e) {
throw new ParameterResolutionException(
String.format("Exception while invoking dataprovider method '%s': %s", dataProviderMethod.getName(),
e.getMessage()),
e);
}
}
/**
* Retrieves the test data from given dataprovider method.
*
* @param dataProviderMethod the dataprovider method that gives the parameters; never {@code null}
* @param cacheDataProviderResult determines if the dataprovider result should be cached using
* {@code dataProviderMethod} as key
* @param context the execution context to use to create a {@link TestInfo} if required; never {@code null}
*
* @return a list of methods, each method bound to a parameter combination returned by the dataprovider
* @throws NullPointerException if and only if one of the given arguments is {@code null}
*/
protected Object invokeDataProviderMethodToRetrieveData(Method dataProviderMethod, boolean cacheDataProviderResult,
ExtensionContext context) {
checkNotNull(dataProviderMethod, "'dataProviderMethod' must not be null");
checkNotNull(context, "'context' must not be null");
Store store = context.getRoot().getStore(NAMESPACE_USE_DATAPROVIDER);
Object cached = store.get(dataProviderMethod);
if (cached != null) {
return cached;
}
try {
// TODO how to not require junit-jupiter-engine dependency and reuse already existing ExtensionRegistry?
ExtensionRegistry extensionRegistry = createRegistryWithDefaultExtensions(
new DefaultJupiterConfiguration(emptyConfigurationParameters()));
Object data = executableInvoker.invoke(dataProviderMethod, context.getTestInstance().orElse(null), context,
extensionRegistry, InvocationInterceptor::interceptTestFactoryMethod);
if (cacheDataProviderResult) {
store.put(dataProviderMethod, data);
}
return data;
} catch (Exception e) {
throw new ParameterResolutionException(
String.format("Exception while invoking dataprovider method '%s': %s", dataProviderMethod.getName(),
e.getMessage()),
e);
}
}
private static Store getStore(ExtensionContext context) {
return context.getRoot().getStore(NAMESPACE);
}
private static Store getStore(ExtensionContext context) {
return context.getRoot().getStore(NAMESPACE);
}
private Store getStore(ExtensionContext context) {
return context.getStore(Namespace.create(getClass(), context));
}
private Store getStore(ExtensionContext context) {
return context.getStore(Namespace.create(getClass(), context));
}
@Override
@SuppressWarnings("unchecked")
public <T> T interceptTestFactoryMethod(
Invocation<T> invocation,
ReflectiveInvocationContext<Method> invocationContext,
ExtensionContext extensionContext) {
WithAccessIds annotation = invocationContext.getExecutable().getAnnotation(WithAccessIds.class);
if (annotation != null) {
// our goal is to run each test returned from the test factory X times. X is the amount of
// WithAccessId annotations. In order to achieve this we are wrapping the result from the
// factory (the returning tests) in a dynamicContainer for each accessId. Since we don't know
// what the factory will return we have to check for every possible return type. All possible
// return types can be found here:
// https://junit.org/junit5/docs/current/user-guide/#writing-tests-dynamic-tests
// After checking each return type we abuse the return type of T and hardly change it to
// Stream<DynamicContainer> no matter what the factory returns. This return type is allowed
// per definition (See link above), but is not the type T. Hence we have an unchecked cast at
// the end to keep the compiler happy...
// we are using the first annotation to run the factory method with.
T factoryResult = performInvocationWithAccessId(invocation, annotation.value()[0]);
Iterable<DynamicNode> newChildrenForDynamicContainer;
// TestFactory must have one of the following return types. See link above for further details
if (factoryResult instanceof DynamicNode) {
newChildrenForDynamicContainer = Collections.singleton((DynamicNode) factoryResult);
} else if (factoryResult instanceof Stream) {
Stream<DynamicNode> nodes = (Stream<DynamicNode>) factoryResult;
newChildrenForDynamicContainer = nodes.collect(Collectors.toList());
} else if (factoryResult instanceof Iterable) {
newChildrenForDynamicContainer = (Iterable<DynamicNode>) factoryResult;
} else if (factoryResult instanceof Iterator) {
newChildrenForDynamicContainer = () -> (Iterator<DynamicNode>) factoryResult;
} else if (factoryResult instanceof DynamicNode[]) {
newChildrenForDynamicContainer = Arrays.asList((DynamicNode[]) factoryResult);
} else {
throw new SystemException(
String.format(
"Testfactory '%s' did not return a proper type",
invocationContext.getExecutable().getName()));
}
// Currently a DynamicContainer has children from this type: Stream<DynamicNode>
// Because of this the children can only be extracted once (Streams can only be operated
// once). This is obviously not ok since we want to execute each node X times. So we have to
// manually persist all children recursively to extract them X times...
Map<String, List<DynamicNode>> childrenMap = new HashMap<>();
persistDynamicContainerChildren(newChildrenForDynamicContainer, childrenMap);
Function<WithAccessId, DynamicContainer> wrapTestsInDynamicContainer =
accessId ->
DynamicContainer.dynamicContainer(
getDisplayNameForAccessId(accessId),
StreamSupport.stream(newChildrenForDynamicContainer.spliterator(), false)
.map(x -> duplicateDynamicNode(x, childrenMap)));
Store store = getStore(extensionContext);
return (T)
Stream.of(annotation.value())
.peek(a -> store.put(ACCESS_IDS_STORE_KEY, a))
.map(wrapTestsInDynamicContainer);
}
return extractAccessIdAndPerformInvocation(invocation, invocationContext.getExecutable());
}
private Store getStore(ExtensionContext context) {
return context.getStore(Namespace.create(getClass(), context));
}