Skip to content

Commit 852cac7

Browse files
Merge pull request #65 from testomatio/optional-dependency-pull
Optional dependency pull
2 parents 15bf1b1 + 52fdaf3 commit 852cac7

File tree

8 files changed

+339
-141
lines changed

8 files changed

+339
-141
lines changed

java-reporter-junit/debug_test.java

Lines changed: 0 additions & 49 deletions
This file was deleted.

java-reporter-junit/pom.xml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>io.testomat</groupId>
88
<artifactId>java-reporter-junit</artifactId>
9-
<version>0.6.8</version>
9+
<version>0.7.2</version>
1010
<packaging>jar</packaging>
1111

1212
<name>Testomat.io Java Reporter JUnit</name>
@@ -49,7 +49,7 @@
4949
<dependency>
5050
<groupId>io.testomat</groupId>
5151
<artifactId>java-reporter-core</artifactId>
52-
<version>0.6.8</version>
52+
<version>0.7.2</version>
5353
</dependency>
5454
<dependency>
5555
<groupId>org.junit.jupiter</groupId>
@@ -61,8 +61,7 @@
6161
<dependency>
6262
<groupId>org.junit.jupiter</groupId>
6363
<artifactId>junit-jupiter-params</artifactId>
64-
<version>5.8.0</version>
65-
<scope>provided</scope>
64+
<version>${junit.version}</version>
6665
<optional>true</optional>
6766
</dependency>
6867
<dependency>

java-reporter-junit/src/main/java/io/testomat/junit/extractor/JunitMetaDataExtractor.java

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import io.testomat.core.exception.NoMethodInContextException;
66
import io.testomat.core.model.TestMetadata;
77
import io.testomat.junit.extractor.strategy.ParameterExtractorService;
8+
import io.testomat.junit.util.ParameterizedTestSupport;
89
import java.lang.reflect.Method;
910
import org.junit.jupiter.api.extension.ExtensionContext;
10-
import org.junit.jupiter.params.ParameterizedTest;
1111

1212
/**
1313
* Extracts metadata and parameters from JUnit test methods.
@@ -68,7 +68,7 @@ public Object extractTestParameters(ExtensionContext context) {
6868
public boolean isParameterizedTest(ExtensionContext context) {
6969
try {
7070
Method method = context.getTestMethod().orElse(null);
71-
return method != null && method.isAnnotationPresent(ParameterizedTest.class);
71+
return ParameterizedTestSupport.isParameterizedTest(method);
7272
} catch (Exception e) {
7373
return false;
7474
}
@@ -81,9 +81,19 @@ private String buildTestTitle(Method method, ExtensionContext context) {
8181
return titleFromAnnotation;
8282
}
8383

84-
ParameterizedTest parameterized = method.getAnnotation(ParameterizedTest.class);
85-
if (parameterized != null) {
86-
return buildParameterizedTitle(method, parameterized);
84+
// Check for ParameterizedTest annotation using reflection
85+
if (ParameterizedTestSupport.isParameterizedTest(method)) {
86+
ParameterizedTestSupport.loadAnnotationClass("ParameterizedTest")
87+
.ifPresent(parameterizedTestClass -> {
88+
try {
89+
Object parameterized = method.getAnnotation(parameterizedTestClass);
90+
if (parameterized != null) {
91+
buildParameterizedTitle(method, parameterized);
92+
}
93+
} catch (Exception e) {
94+
// Ignore reflection errors
95+
}
96+
});
8797
}
8898

8999
return method.getName();
@@ -92,12 +102,18 @@ private String buildTestTitle(Method method, ExtensionContext context) {
92102
}
93103
}
94104

95-
private String buildParameterizedTitle(Method method, ParameterizedTest parameterized) {
96-
String customName = parameterized.name();
97-
if (isCustomNameProvided(customName)) {
105+
private String buildParameterizedTitle(Method method, Object parameterized) {
106+
try {
107+
// Use reflection to safely access the name() method
108+
java.lang.reflect.Method nameMethod = parameterized.getClass().getMethod("name");
109+
String customName = (String) nameMethod.invoke(parameterized);
110+
if (isCustomNameProvided(customName)) {
111+
return method.getName();
112+
}
113+
return method.getName();
114+
} catch (Exception e) {
98115
return method.getName();
99116
}
100-
return method.getName();
101117
}
102118

103119
private boolean isCustomNameProvided(String name) {

java-reporter-junit/src/main/java/io/testomat/junit/extractor/strategy/ParameterHandlerRegistry.java

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,11 @@
1010
import io.testomat.junit.extractor.strategy.handlers.NullSourceHandler;
1111
import io.testomat.junit.extractor.strategy.handlers.ParameterExtractionHandler;
1212
import io.testomat.junit.extractor.strategy.handlers.ValueSourceHandler;
13+
import io.testomat.junit.util.ParameterizedTestSupport;
1314
import java.lang.annotation.Annotation;
1415
import java.util.HashMap;
1516
import java.util.Map;
1617
import java.util.Optional;
17-
import org.junit.jupiter.params.provider.ArgumentsSource;
18-
import org.junit.jupiter.params.provider.CsvFileSource;
19-
import org.junit.jupiter.params.provider.CsvSource;
20-
import org.junit.jupiter.params.provider.EmptySource;
21-
import org.junit.jupiter.params.provider.EnumSource;
22-
import org.junit.jupiter.params.provider.MethodSource;
23-
import org.junit.jupiter.params.provider.NullAndEmptySource;
24-
import org.junit.jupiter.params.provider.NullSource;
25-
import org.junit.jupiter.params.provider.ValueSource;
2618

2719
/**
2820
* Registry that maintains direct mapping between JUnit parameter source annotations
@@ -64,14 +56,19 @@ public ParameterHandlerRegistry(Map<Class<? extends Annotation>,
6456
* @throws IllegalStateException if multiple conflicting handlers are found
6557
*/
6658
public Optional<ParameterExtractionHandler> findHandler(ParameterExtractionContext context) {
67-
if (!context.isValid()) {
59+
if (!context.isValid() || !ParameterizedTestSupport.isAvailable()) {
6860
return Optional.empty();
6961
}
7062

7163
ParameterExtractionHandler foundHandler = null;
7264
Class<? extends Annotation> foundAnnotation = null;
7365

7466
for (Annotation annotation : context.getAnnotations()) {
67+
// Only process JUnit params annotations
68+
if (!ParameterizedTestSupport.isJunitParamsAnnotation(annotation)) {
69+
continue;
70+
}
71+
7572
Class<? extends Annotation> annotationType = annotation.annotationType();
7673
ParameterExtractionHandler handler = handlerMap.get(annotationType);
7774

@@ -92,14 +89,24 @@ public Optional<ParameterExtractionHandler> findHandler(ParameterExtractionConte
9289
}
9390

9491
private void registerDefaultHandlers() {
95-
handlerMap.put(ValueSource.class, new ValueSourceHandler());
96-
handlerMap.put(EnumSource.class, new EnumSourceHandler());
97-
handlerMap.put(CsvSource.class, new CsvSourceHandler());
98-
handlerMap.put(CsvFileSource.class, new CsvFileSourceHandler());
99-
handlerMap.put(MethodSource.class, new MethodSourceHandler());
100-
handlerMap.put(ArgumentsSource.class, new ArgumentsSourceHandler());
101-
handlerMap.put(NullAndEmptySource.class, new NullAndEmptySourceHandler());
102-
handlerMap.put(NullSource.class, new NullSourceHandler());
103-
handlerMap.put(EmptySource.class, new EmptySourceHandler());
92+
// Only register handlers if JUnit params is available
93+
if (!ParameterizedTestSupport.isAvailable()) {
94+
return;
95+
}
96+
97+
registerHandler("ValueSource", new ValueSourceHandler());
98+
registerHandler("EnumSource", new EnumSourceHandler());
99+
registerHandler("CsvSource", new CsvSourceHandler());
100+
registerHandler("CsvFileSource", new CsvFileSourceHandler());
101+
registerHandler("MethodSource", new MethodSourceHandler());
102+
registerHandler("ArgumentsSource", new ArgumentsSourceHandler());
103+
registerHandler("NullAndEmptySource", new NullAndEmptySourceHandler());
104+
registerHandler("NullSource", new NullSourceHandler());
105+
registerHandler("EmptySource", new EmptySourceHandler());
106+
}
107+
108+
private void registerHandler(String annotationName, ParameterExtractionHandler handler) {
109+
ParameterizedTestSupport.loadAnnotationClass(annotationName)
110+
.ifPresent(annotationClass -> handlerMap.put(annotationClass, handler));
104111
}
105112
}

java-reporter-junit/src/main/java/io/testomat/junit/extractor/strategy/handlers/EnumSourceHandler.java

Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package io.testomat.junit.extractor.strategy.handlers;
22

33
import io.testomat.junit.extractor.strategy.ParameterExtractionContext;
4+
import io.testomat.junit.util.ParameterizedTestSupport;
5+
import java.lang.annotation.Annotation;
46
import java.lang.reflect.Method;
57
import java.lang.reflect.Parameter;
6-
import org.junit.jupiter.params.provider.EnumSource;
78

89
/**
910
* Parameter extraction handler for @EnumSource annotated parameterized tests.
@@ -24,14 +25,31 @@ protected Object parseDisplayNameValue(String valueStr, ParameterExtractionConte
2425

2526
@Override
2627
protected Object extractFromAnnotation(ParameterExtractionContext context) {
27-
EnumSource enumSource = context.getAnnotation(EnumSource.class);
28-
if (enumSource == null) {
28+
if (!ParameterizedTestSupport.isAvailable()) {
2929
return null;
3030
}
31+
32+
return ParameterizedTestSupport.loadAnnotationClass("EnumSource")
33+
.map(enumSourceClass -> {
34+
Annotation enumSource = context.getAnnotation(enumSourceClass);
35+
if (enumSource == null) {
36+
return null;
37+
}
38+
return extractValueFromEnumSource(enumSource, context);
39+
})
40+
.orElse(null);
41+
}
42+
43+
private Object extractValueFromEnumSource(Annotation enumSource,
44+
ParameterExtractionContext context) {
3145
try {
32-
Class<? extends Enum<?>> enumClass = enumSource.value();
46+
Class<?> annotationClass = enumSource.annotationType();
3347

34-
if (enumClass.getName().equals("org.junit.jupiter.params.provider.NullEnum")) {
48+
java.lang.reflect.Method valueMethod = annotationClass.getMethod("value");
49+
Class<? extends Enum<?>> enumClass =
50+
(Class<? extends Enum<?>>) valueMethod.invoke(enumSource);
51+
52+
if (isNullEnum(enumClass)) {
3553
enumClass = inferEnumClassFromMethod(context);
3654
}
3755

@@ -44,16 +62,11 @@ protected Object extractFromAnnotation(ParameterExtractionContext context) {
4462
return null;
4563
}
4664

47-
String[] names = enumSource.names();
65+
java.lang.reflect.Method namesMethod = annotationClass.getMethod("names");
66+
String[] names = (String[]) namesMethod.invoke(enumSource);
67+
4868
if (names.length > 0) {
49-
for (String name : names) {
50-
try {
51-
return Enum.valueOf((Class) enumClass, name);
52-
} catch (IllegalArgumentException e) {
53-
logger.warn("Could not find enum constant {}", name);
54-
}
55-
}
56-
return null;
69+
return findFirstValidEnumConstant(enumClass, names);
5770
}
5871

5972
return enumConstants[0];
@@ -64,6 +77,22 @@ protected Object extractFromAnnotation(ParameterExtractionContext context) {
6477
}
6578
}
6679

80+
private boolean isNullEnum(Class<? extends Enum<?>> enumClass) {
81+
return enumClass.getName().equals("org.junit.jupiter.params.provider.NullEnum");
82+
}
83+
84+
private Object findFirstValidEnumConstant(Class<? extends Enum<?>> enumClass,
85+
String[] names) {
86+
for (String name : names) {
87+
try {
88+
return Enum.valueOf((Class) enumClass, name);
89+
} catch (IllegalArgumentException e) {
90+
logger.warn("Could not find enum constant {}", name);
91+
}
92+
}
93+
return null;
94+
}
95+
6796
@SuppressWarnings("unchecked")
6897
private Class<? extends Enum<?>> inferEnumClassFromMethod(ParameterExtractionContext context) {
6998
Method method = context.getTestMethod();
@@ -95,26 +124,52 @@ private Object parseEnumValue(String value, ParameterExtractionContext context)
95124
return null;
96125
}
97126

127+
if (!ParameterizedTestSupport.isAvailable()) {
128+
return value;
129+
}
130+
98131
try {
99-
EnumSource enumSource = context.getAnnotation(EnumSource.class);
100-
Class<? extends Enum<?>> enumClass = enumSource.value();
132+
return ParameterizedTestSupport.loadAnnotationClass("EnumSource")
133+
.map(enumSourceClass -> {
134+
Annotation enumSource = context.getAnnotation(enumSourceClass);
135+
if (enumSource == null) {
136+
return value;
137+
}
138+
return parseEnumWithReflection(enumSource, trimmed, context);
139+
})
140+
.orElse(value);
141+
} catch (Exception e) {
142+
logger.debug("Failed to parse enum value: {}", trimmed, e);
143+
return value;
144+
}
145+
}
101146

102-
if (enumClass.getName().equals("org.junit.jupiter.params.provider.NullEnum")) {
147+
private Object parseEnumWithReflection(Annotation enumSource, String trimmed,
148+
ParameterExtractionContext context) {
149+
try {
150+
Method valueMethod = enumSource.annotationType().getMethod("value");
151+
Class<? extends Enum<?>> enumClass =
152+
(Class<? extends Enum<?>>) valueMethod.invoke(enumSource);
153+
154+
if (isNullEnum(enumClass)) {
103155
enumClass = inferEnumClassFromMethod(context);
104156
}
105157

106158
if (enumClass != null) {
107-
String enumName = trimmed;
108-
if (trimmed.contains(".")) {
109-
enumName = trimmed.substring(trimmed.lastIndexOf('.') + 1);
110-
}
111-
159+
String enumName = extractEnumName(trimmed);
112160
return Enum.valueOf((Class) enumClass, enumName);
113161
}
114162
} catch (Exception e) {
115-
logger.debug("Failed to parse enum value: {}", trimmed, e);
163+
logger.debug("Failed to parse enum value with reflection: {}", trimmed, e);
116164
}
117165

118-
return value;
166+
return trimmed;
167+
}
168+
169+
private String extractEnumName(String trimmed) {
170+
if (trimmed.contains(".")) {
171+
return trimmed.substring(trimmed.lastIndexOf('.') + 1);
172+
}
173+
return trimmed;
119174
}
120175
}

0 commit comments

Comments
 (0)