Skip to content

Commit 5d83a6b

Browse files
committed
UNit Tests for Processor.
1 parent f1f57d8 commit 5d83a6b

File tree

5 files changed

+230
-10
lines changed

5 files changed

+230
-10
lines changed

additions/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ dependencies {
77

88
testImplementation 'org.assertj:assertj-core:3.15.0'
99
testImplementation 'commons-io:commons-io:2.6'
10+
testImplementation 'com.google.guava:guava:28.2-jre'
11+
testImplementation 'org.mockito:mockito-junit-jupiter:3.3.3'
1012
}

additions/src/main/java/uk/co/kleindelao/mapstruct/spring/converter/ConversionServiceBridgeGenerator.java renamed to additions/src/main/java/uk/co/kleindelao/mapstruct/spring/converter/ConversionServiceAdapterGenerator.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
import java.time.format.DateTimeFormatter;
1313
import org.springframework.core.convert.ConversionService;
1414

15-
public class ConversionServiceBridgeGenerator {
15+
public class ConversionServiceAdapterGenerator {
1616
private final Clock clock;
1717

18-
public ConversionServiceBridgeGenerator(final Clock clock) {
18+
public ConversionServiceAdapterGenerator(final Clock clock) {
1919
this.clock = clock;
2020
}
2121

@@ -82,7 +82,7 @@ private static FieldSpec buildInjectedConversionServiceFieldSpec() {
8282

8383
private AnnotationSpec buildGeneratedAnnotationSpec() {
8484
return AnnotationSpec.builder(ClassName.get("javax.annotation", "Generated"))
85-
.addMember("value", "$S", ConversionServiceBridgeGenerator.class.getName())
85+
.addMember("value", "$S", ConversionServiceAdapterGenerator.class.getName())
8686
.addMember("date", "$S", DateTimeFormatter.ISO_INSTANT.format(ZonedDateTime.now(clock)))
8787
.build();
8888
}

additions/src/main/java/uk/co/kleindelao/mapstruct/spring/converter/ConverterMapperProcessor.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,16 @@ public class ConverterMapperProcessor extends AbstractProcessor {
3939
protected static final String SPRING_MAPPER_CONFIG =
4040
"uk.co.kleindelao.mapstruct.spring.SpringMapperConfig";
4141

42-
private final ConversionServiceBridgeGenerator bridgeGenerator =
43-
new ConversionServiceBridgeGenerator(Clock.systemUTC());
42+
private final ConversionServiceAdapterGenerator adapterGenerator;
43+
44+
public ConverterMapperProcessor() {
45+
this(new ConversionServiceAdapterGenerator(Clock.systemUTC()));
46+
}
47+
48+
ConverterMapperProcessor(final ConversionServiceAdapterGenerator adapterGenerator) {
49+
super();
50+
this.adapterGenerator = adapterGenerator;
51+
}
4452

4553
@Override
4654
public SourceVersion getSupportedSourceVersion() {
@@ -118,7 +126,7 @@ private void writeBridgeClassFile(
118126
.createSourceFile(
119127
bridgePackageAndClass.getLeft() + "." + bridgePackageAndClass.getRight())
120128
.openWriter()) {
121-
bridgeGenerator.writeConversionServiceBridge(descriptor, outputWriter);
129+
adapterGenerator.writeConversionServiceBridge(descriptor, outputWriter);
122130
} catch (IOException e) {
123131
processingEnv
124132
.getMessager()

additions/src/test/java/uk/co/kleindelao/mapstruct/spring/converter/ConversionServiceBridgeGeneratorTest.java renamed to additions/src/test/java/uk/co/kleindelao/mapstruct/spring/converter/ConversionServiceAdapterGeneratorTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,22 @@
1414
import org.apache.commons.lang3.tuple.Pair;
1515
import org.junit.jupiter.api.Test;
1616

17-
class ConversionServiceBridgeGeneratorTest {
17+
class ConversionServiceAdapterGeneratorTest {
1818
private static final Clock FIXED_CLOCK =
1919
Clock.fixed(
2020
ZonedDateTime.of(2020, 3, 29, 15, 21, 34, (int) (236 * Math.pow(10, 6)), ZoneId.of("Z"))
2121
.toInstant(),
2222
ZoneId.of("Z"));
23-
private final ConversionServiceBridgeGenerator generator =
24-
new ConversionServiceBridgeGenerator(FIXED_CLOCK);
23+
private final ConversionServiceAdapterGenerator generator =
24+
new ConversionServiceAdapterGenerator(FIXED_CLOCK);
2525

2626
@Test
2727
void shouldGenerateMatchingOutput() throws IOException {
2828
// Given
2929
final ConversionServiceBridgeDescriptor descriptor = new ConversionServiceBridgeDescriptor();
3030
descriptor.setBridgeClassName(
3131
ClassName.get(
32-
ConversionServiceBridgeGeneratorTest.class.getPackage().getName(),
32+
ConversionServiceAdapterGeneratorTest.class.getPackage().getName(),
3333
"ConversionServiceBridge"));
3434
descriptor.setFromToMappings(
3535
singletonList(Pair.of(ClassName.get("test", "Car"), ClassName.get("test", "CarDto"))));
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
package uk.co.kleindelao.mapstruct.spring.converter;
2+
3+
import static com.google.common.collect.Iterables.concat;
4+
import static java.nio.file.Files.createTempDirectory;
5+
import static java.util.Arrays.asList;
6+
import static java.util.Collections.singletonList;
7+
import static javax.lang.model.element.Modifier.*;
8+
import static javax.tools.StandardLocation.CLASS_OUTPUT;
9+
import static org.assertj.core.api.BDDAssertions.then;
10+
import static org.mockito.ArgumentMatchers.any;
11+
12+
import com.google.common.collect.ImmutableSet;
13+
import com.squareup.javapoet.*;
14+
import java.io.IOException;
15+
import java.io.Writer;
16+
import java.time.Clock;
17+
import java.util.Set;
18+
import javax.tools.*;
19+
import org.apache.commons.lang3.tuple.Pair;
20+
import org.junit.jupiter.api.BeforeAll;
21+
import org.junit.jupiter.api.Test;
22+
import org.junit.jupiter.api.extension.ExtendWith;
23+
import org.mapstruct.Mapper;
24+
import org.mockito.*;
25+
import org.mockito.junit.jupiter.MockitoExtension;
26+
import org.springframework.core.convert.converter.Converter;
27+
28+
@ExtendWith(MockitoExtension.class)
29+
class ConverterMapperProcessorTest {
30+
@Spy
31+
private ConversionServiceAdapterGenerator adapterGenerator =
32+
new ConversionServiceAdapterGenerator(Clock.systemUTC());
33+
34+
@InjectMocks private ConverterMapperProcessor processor;
35+
36+
@Captor private ArgumentCaptor<ConversionServiceBridgeDescriptor> descriptorArgumentCaptor;
37+
38+
private static Set<JavaFileObject> commonCompilationUnits;
39+
private static final String PACKAGE_NAME = "test";
40+
41+
private boolean compile(JavaFileObject... additionalCompilationUnits) throws IOException {
42+
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
43+
44+
final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
45+
final StandardJavaFileManager fileManager =
46+
compiler.getStandardFileManager(diagnostics, null, null);
47+
fileManager.setLocation(CLASS_OUTPUT, singletonList(createTempDirectory("classes").toFile()));
48+
49+
final JavaCompiler.CompilationTask task =
50+
compiler.getTask(
51+
null,
52+
fileManager,
53+
diagnostics,
54+
null,
55+
null,
56+
concat(commonCompilationUnits, asList(additionalCompilationUnits)));
57+
task.setProcessors(singletonList(processor));
58+
59+
final boolean success = task.call();
60+
diagnostics.getDiagnostics().forEach(System.err::println);
61+
return success;
62+
}
63+
64+
@BeforeAll
65+
static void setupCommonSourceFiles() {
66+
commonCompilationUnits =
67+
ImmutableSet.of(
68+
JavaFile.builder(PACKAGE_NAME, buildModelClassTypeSpec("Car"))
69+
.skipJavaLangImports(true)
70+
.build()
71+
.toJavaFileObject(),
72+
JavaFile.builder(PACKAGE_NAME, buildModelClassTypeSpec("CarDto"))
73+
.skipJavaLangImports(true)
74+
.build()
75+
.toJavaFileObject(),
76+
JavaFile.builder("javax.annotation", buildGeneratedAnnotationTypeSpec())
77+
.skipJavaLangImports(true)
78+
.build()
79+
.toJavaFileObject(),
80+
JavaFile.builder(
81+
"org.springframework.beans.factory.annotation",
82+
buildSimpleAnnotationTypeSpec("Autowired"))
83+
.skipJavaLangImports(true)
84+
.build()
85+
.toJavaFileObject(),
86+
JavaFile.builder(
87+
"org.springframework.stereotype", buildSimpleAnnotationTypeSpec("Component"))
88+
.skipJavaLangImports(true)
89+
.build()
90+
.toJavaFileObject());
91+
}
92+
93+
private static TypeSpec buildSimpleAnnotationTypeSpec(final String anotationName) {
94+
return TypeSpec.annotationBuilder(anotationName).addModifiers(PUBLIC).build();
95+
}
96+
97+
private static TypeSpec buildGeneratedAnnotationTypeSpec() {
98+
return TypeSpec.annotationBuilder("Generated")
99+
.addModifiers(PUBLIC)
100+
.addMethod(
101+
MethodSpec.methodBuilder("value")
102+
.returns(String.class)
103+
.addModifiers(PUBLIC, ABSTRACT)
104+
.build())
105+
.addMethod(
106+
MethodSpec.methodBuilder("date")
107+
.returns(String.class)
108+
.addModifiers(PUBLIC, ABSTRACT)
109+
.build())
110+
.build();
111+
}
112+
113+
private static TypeSpec buildModelClassTypeSpec(final String className) {
114+
final FieldSpec makeField = FieldSpec.builder(String.class, "make", PRIVATE).build();
115+
final ParameterSpec makeParameter = ParameterSpec.builder(String.class, "make", FINAL).build();
116+
return TypeSpec.classBuilder(className)
117+
.addModifiers(PUBLIC)
118+
.addField(makeField)
119+
.addMethod(
120+
MethodSpec.methodBuilder("getMake")
121+
.returns(String.class)
122+
.addStatement("return $N", makeField)
123+
.build())
124+
.addMethod(
125+
MethodSpec.methodBuilder("setMake")
126+
.addParameter(makeParameter)
127+
.addStatement("this.$N = $N", makeField, makeParameter)
128+
.build())
129+
.build();
130+
}
131+
132+
@Test
133+
void shouldCompileSimpleConverterMapper() throws IOException {
134+
// Given
135+
final JavaFile mapperFile =
136+
JavaFile.builder(PACKAGE_NAME, converterMapperBuilder().build()).build();
137+
138+
// When
139+
final boolean compileResult = compile(mapperFile.toJavaFileObject());
140+
141+
// Then
142+
then(compileResult).isTrue();
143+
}
144+
145+
private static TypeSpec.Builder converterMapperBuilder() {
146+
return plainCarMapperBuilder()
147+
.addSuperinterface(
148+
ParameterizedTypeName.get(
149+
ClassName.get(Converter.class),
150+
ClassName.get("test", "Car"),
151+
ClassName.get("test", "CarDto")));
152+
}
153+
154+
private static TypeSpec.Builder plainCarMapperBuilder() {
155+
return TypeSpec.interfaceBuilder("CarMapper")
156+
.addAnnotation(Mapper.class)
157+
.addMethod(convertMethod("Car", "CarDto"));
158+
}
159+
160+
private static MethodSpec convertMethod(final String parameterType, final String returnType) {
161+
return MethodSpec.methodBuilder("convert")
162+
.addModifiers(PUBLIC, ABSTRACT)
163+
.addParameter(ClassName.get("test", parameterType), "car")
164+
.returns(ClassName.get("test", returnType))
165+
.build();
166+
}
167+
168+
@Test
169+
void shouldIgnoreNonConverterMappers() throws IOException {
170+
// Given
171+
final JavaFile plainMapperFile =
172+
JavaFile.builder(PACKAGE_NAME, plainCarMapperBuilder().build()).build();
173+
174+
// When
175+
final boolean compileResult = compile(plainMapperFile.toJavaFileObject());
176+
177+
// Then
178+
then(compileResult).isTrue();
179+
BDDMockito.then(adapterGenerator)
180+
.should()
181+
.writeConversionServiceBridge(descriptorArgumentCaptor.capture(), any(Writer.class));
182+
final ConversionServiceBridgeDescriptor descriptor = descriptorArgumentCaptor.getValue();
183+
then(descriptor).isNotNull();
184+
then(descriptor.getFromToMappings()).isEmpty();
185+
}
186+
187+
@Test
188+
void shouldProcessOnlyConvertMethodForMapperWithMultipleMethods() throws IOException {
189+
// Given
190+
final JavaFile mapperFile =
191+
JavaFile.builder(
192+
PACKAGE_NAME,
193+
converterMapperBuilder().addMethod(convertMethod("CarDto", "Car")).build())
194+
.build();
195+
196+
// When
197+
final boolean compileResult = compile(mapperFile.toJavaFileObject());
198+
199+
// Then
200+
then(compileResult).isTrue();
201+
BDDMockito.then(adapterGenerator)
202+
.should()
203+
.writeConversionServiceBridge(descriptorArgumentCaptor.capture(), any(Writer.class));
204+
final ConversionServiceBridgeDescriptor descriptor = descriptorArgumentCaptor.getValue();
205+
then(descriptor).isNotNull();
206+
then(descriptor.getFromToMappings())
207+
.hasSize(1)
208+
.containsExactly(Pair.of(ClassName.get("test", "Car"), ClassName.get("test", "CarDto")));
209+
}
210+
}

0 commit comments

Comments
 (0)