Skip to content

Commit

Permalink
Support Test Resources from @testprofile in native mode
Browse files Browse the repository at this point in the history
## Description
In quarkusio#13154, the annotation `@TestProfile` was supported also in Native tests. However, the native extension was not processing the test resources in the test profile like:

```
public class ConfluentTestProfile implements QuarkusTestProfile {

    @OverRide
    public String getConfigProfile() {
        return "confluent";
    }

    @OverRide
    public List<TestResourceEntry> testResources() {
        return Collections.singletonList(new TestResourceEntry(ConfluentKafkaResource.class));
    }
}
```

This PR makes the above to be supported.
The solution behaves the same as done in the Quarkus Test extension.
  • Loading branch information
Sgitario authored and patrox committed Jun 23, 2021
1 parent d336084 commit 346b41e
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 35 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.quarkus.it.nat.test.profile;

import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.NativeImageTest;

/**
* This test ensures that the NativeTestExtension starts the test resources from the Test Profile annotation.
*/
@NativeImageTest
public class RuntimeValueChangeFromTestResourcesIT extends RuntimeValueChangeFromTestResourcesTest {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.quarkus.it.nat.test.profile;

import static org.hamcrest.Matchers.is;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.junit.jupiter.api.Test;

import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.QuarkusTestProfile;
import io.quarkus.test.junit.TestProfile;
import io.restassured.RestAssured;

@QuarkusTest
@TestProfile(RuntimeValueChangeFromTestResourcesTest.CustomTestProfile.class)
public class RuntimeValueChangeFromTestResourcesTest {

private static final String EXPECTED_VALUE = "RuntimeTimeValueChangeFromTestResources";

@Test
public void failInNativeTestExtension_beforeEach() {
RestAssured.when()
.get("/native-config-profile/myConfigValue")
.then()
.body(is(EXPECTED_VALUE));
}

public static class CustomTestProfile implements QuarkusTestProfile {
@Override
public List<TestResourceEntry> testResources() {
return Collections.singletonList(new TestResourceEntry(DummyTestResource.class));
}
}

/**
* This only used to ensure that the TestResource has been handled correctly by the QuarkusTestExtension
*/
public static class DummyTestResource implements QuarkusTestResourceLifecycleManager {

@Override
public Map<String, String> start() {
return Collections.singletonMap("my.config.value", EXPECTED_VALUE);
}

@Override
public void stop() {
// do nothing
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.net.URI;
import java.net.URISyntaxException;
Expand All @@ -15,7 +17,10 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
Expand All @@ -41,6 +46,7 @@
import io.quarkus.test.common.ArtifactLauncher;
import io.quarkus.test.common.PathTestHelper;
import io.quarkus.test.common.TestClassIndexer;
import io.quarkus.test.common.TestResourceManager;
import io.quarkus.test.common.http.TestHTTPResourceManager;

final class IntegrationTestUtil {
Expand Down Expand Up @@ -125,6 +131,38 @@ static TestProfileAndProperties determineTestProfileAndProperties(Class<? extend
return new TestProfileAndProperties(testProfile, properties);
}

/**
* Since {@link TestResourceManager} is loaded from the ClassLoader passed in as an argument,
* we need to convert the user input {@link QuarkusTestProfile.TestResourceEntry} into instances of
* {@link TestResourceManager.TestResourceClassEntry}
* that are loaded from that ClassLoader
*/
static <T> List<T> getAdditionalTestResources(
QuarkusTestProfile profileInstance, ClassLoader classLoader) {
if ((profileInstance == null) || profileInstance.testResources().isEmpty()) {
return Collections.emptyList();
}

try {
Constructor<?> testResourceClassEntryConstructor = Class
.forName(TestResourceManager.TestResourceClassEntry.class.getName(), true, classLoader)
.getConstructor(Class.class, Map.class, Annotation.class, boolean.class);

List<QuarkusTestProfile.TestResourceEntry> testResources = profileInstance.testResources();
List<T> result = new ArrayList<>(testResources.size());
for (QuarkusTestProfile.TestResourceEntry testResource : testResources) {
T instance = (T) testResourceClassEntryConstructor.newInstance(
Class.forName(testResource.getClazz().getName(), true, classLoader), testResource.getArgs(),
null, testResource.isParallel());
result.add(instance);
}

return result;
} catch (Exception e) {
throw new IllegalStateException("Unable to handle profile " + profileInstance.getClass(), e);
}
}

static void startLauncher(ArtifactLauncher launcher, Map<String, String> additionalProperties, Runnable sslSetter)
throws IOException {
launcher.addSystemProperties(additionalProperties);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
import static io.quarkus.test.junit.IntegrationTestUtil.determineTestProfileAndProperties;
import static io.quarkus.test.junit.IntegrationTestUtil.doProcessTestInstance;
import static io.quarkus.test.junit.IntegrationTestUtil.ensureNoInjectAnnotationIsUsed;
import static io.quarkus.test.junit.IntegrationTestUtil.getAdditionalTestResources;
import static io.quarkus.test.junit.IntegrationTestUtil.getSysPropsToRestore;
import static io.quarkus.test.junit.IntegrationTestUtil.handleDevDb;
import static io.quarkus.test.junit.IntegrationTestUtil.startLauncher;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -113,7 +113,8 @@ private IntegrationTestExtensionState doNativeStart(ExtensionContext context, Cl
TestProfileAndProperties testProfileAndProperties = determineTestProfileAndProperties(profile, sysPropRestore);

testResourceManager = new TestResourceManager(requiredTestClass, quarkusTestProfile,
Collections.emptyList(), testProfileAndProperties.testProfile != null
getAdditionalTestResources(testProfileAndProperties.testProfile, currentJUnitTestClass.getClassLoader()),
testProfileAndProperties.testProfile != null
&& testProfileAndProperties.testProfile.disableGlobalTestResources());
testResourceManager.init();
hasPerTestResources = testResourceManager.hasPerTestResources();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static io.quarkus.test.common.PathTestHelper.getAppClassLocationForTestLocation;
import static io.quarkus.test.common.PathTestHelper.getTestClassesLocation;
import static io.quarkus.test.junit.IntegrationTestUtil.getAdditionalTestResources;

import java.io.Closeable;
import java.io.IOException;
Expand All @@ -19,7 +20,6 @@
import java.util.AbstractMap;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -426,38 +426,6 @@ public void close() throws IOException {
}
}

/**
* Since {@link TestResourceManager} is loaded from the ClassLoader passed in as an argument,
* we need to convert the user input {@link QuarkusTestProfile.TestResourceEntry} into instances of
* {@link TestResourceManager.TestResourceClassEntry}
* that are loaded from that ClassLoader
*/
private List<Object> getAdditionalTestResources(
QuarkusTestProfile profileInstance, ClassLoader classLoader) {
if ((profileInstance == null) || profileInstance.testResources().isEmpty()) {
return Collections.emptyList();
}

try {
Constructor<?> testResourceClassEntryConstructor = Class
.forName(TestResourceManager.TestResourceClassEntry.class.getName(), true, classLoader)
.getConstructor(Class.class, Map.class, Annotation.class, boolean.class);

List<QuarkusTestProfile.TestResourceEntry> testResources = profileInstance.testResources();
List<Object> result = new ArrayList<>(testResources.size());
for (QuarkusTestProfile.TestResourceEntry testResource : testResources) {
Object instance = testResourceClassEntryConstructor.newInstance(
Class.forName(testResource.getClazz().getName(), true, classLoader), testResource.getArgs(),
null, testResource.isParallel());
result.add(instance);
}

return result;
} catch (Exception e) {
throw new IllegalStateException("Unable to handle profile " + profileInstance.getClass(), e);
}
}

private void populateDeepCloneField(StartupAction startupAction) {
deepClone = new SerializationWithXStreamFallbackDeepClone(startupAction.getClassLoader());
}
Expand Down

0 comments on commit 346b41e

Please sign in to comment.