Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.quarkus.it.main;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.util.Arrays;
import java.util.List;

import javax.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestFactory;

import io.quarkus.it.arc.UnusedBean;
import io.quarkus.test.junit.QuarkusDynamicTest;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class DynamicTestsTestCase {

@Inject
UnusedBean bean;

@Test
public void testInjection() {
assertNotNull(bean);
}

@TestFactory
public List<?> dynamicTests() {
return Arrays.asList(
QuarkusDynamicTest.dynamicTest("test 1", () -> {
assertNotNull(bean);
}),
QuarkusDynamicTest.dynamicTest("test 2", () -> {
assertEquals(1, 1);
}));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.quarkus.test.junit;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import org.junit.jupiter.api.function.Executable;

/**
* This class needs to be used when users want to use JUnit 5's {@link org.junit.jupiter.api.DynamicTest} along with
* {@link org.junit.jupiter.api.TestFactory} in a {@link QuarkusTest}.
*
*
* An example usage in a test is:
*
* <code><pre>
* &#64;TestFactory
* public List<?> dynamicTests() {
* return Arrays.asList(
* QuarkusDynamicTest.dynamicTest("test 1", () -> {
* assertEquals(1, 1);
* // of course more complex things can be done here, like accessing a field injected with @Inject
* }),
* QuarkusDynamicTest.dynamicTest("test 2", () -> {
* assertEquals(2, 2);
* })
* );
* }
* </pre></code>
*/
public class QuarkusDynamicTest {

private static ClassLoader cl;
private static Method dynamicTestMethod;
private static Constructor<?> quarkusExecutableClassConstructor;

public static Object dynamicTest(String displayName, Executable executable) {
try {
Object executableInstance = getQuarkusExecutableClassConstructor().newInstance(executable);
return getDynamicTestMethod().invoke(null, displayName, executableInstance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

static void setClassLoader(ClassLoader classLoader) {
cl = classLoader;
}

private static Method getDynamicTestMethod() throws ClassNotFoundException, NoSuchMethodException {
if (dynamicTestMethod == null) {
dynamicTestMethod = Class.forName("org.junit.jupiter.api.DynamicTest", false, cl)
.getMethod("dynamicTest", String.class, Class
.forName("org.junit.jupiter.api.function.Executable", false, cl));
}
return dynamicTestMethod;
}

private static Constructor<?> getQuarkusExecutableClassConstructor() throws ClassNotFoundException, NoSuchMethodException {
if (quarkusExecutableClassConstructor == null) {
quarkusExecutableClassConstructor = Class.forName("io.quarkus.test.junit.QuarkusExecutable", false, cl)
.getConstructor(Object.class);
}
return quarkusExecutableClassConstructor;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.quarkus.test.junit;

import java.lang.reflect.Method;

import org.junit.jupiter.api.function.Executable;

public class QuarkusExecutable implements Executable {

private final Object executable;
private final Method executeMethod;

public QuarkusExecutable(Object executable) {
this.executable = executable;
try {
this.executeMethod = executable.getClass().getMethod("execute");
this.executeMethod.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(e);
}
}

@Override
public void execute() throws Throwable {
executeMethod.invoke(executable);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ private ExtensionState doJavaStart(ExtensionContext context) throws Throwable {
.newInstance(context.getRequiredTestClass());
testResourceManager.getClass().getMethod("start").invoke(testResourceManager);

handleDynamicTests(startupAction.getClassLoader());

runningQuarkusApplication = startupAction.run();

ConfigProviderResolver.setInstance(new RunningAppConfigResolver(runningQuarkusApplication));
Expand Down Expand Up @@ -153,6 +155,14 @@ public void run() {
}
}

private void handleDynamicTests(ClassLoader startupActionClassLoader)
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Class<?> quarkusDynamicTestClass = startupActionClassLoader.loadClass(QuarkusDynamicTest.class.getName());
Method setClassLoaderMethod = quarkusDynamicTestClass.getDeclaredMethod("setClassLoader", ClassLoader.class);
setClassLoaderMethod.setAccessible(true);
setClassLoaderMethod.invoke(null, originalCl);
}

@Override
public void afterEach(ExtensionContext context) throws Exception {
if (isNativeTest(context)) {
Expand Down Expand Up @@ -320,6 +330,17 @@ public void interceptTestTemplateMethod(Invocation<Void> invocation, ReflectiveI
invocation.skip();
}

@Override
public <T> T interceptTestFactoryMethod(Invocation<T> invocation,
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
if (isNativeTest(extensionContext)) {
return invocation.proceed();
}
T result = (T) runExtensionMethod(invocationContext, extensionContext);
invocation.skip();
return result;
}

@Override
public void interceptAfterEachMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext,
ExtensionContext extensionContext) throws Throwable {
Expand All @@ -342,7 +363,7 @@ public void interceptAfterAllMethod(Invocation<Void> invocation, ReflectiveInvoc
invocation.skip();
}

private void runExtensionMethod(ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext)
private Object runExtensionMethod(ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext)
throws Throwable {
Method newMethod = null;

Expand Down Expand Up @@ -389,7 +410,7 @@ private void runExtensionMethod(ReflectiveInvocationContext<Method> invocationCo
}
}

newMethod.invoke(actualTestInstance, argumentsFromTccl.toArray(new Object[0]));
return newMethod.invoke(actualTestInstance, argumentsFromTccl.toArray(new Object[0]));
} catch (InvocationTargetException e) {
throw e.getCause();
} catch (IllegalAccessException | ClassNotFoundException e) {
Expand Down