diff --git a/src/main/java/org/wiremock/spring/internal/WireMockContextCustomizerFactory.java b/src/main/java/org/wiremock/spring/internal/WireMockContextCustomizerFactory.java index 95405b2..917c6e1 100644 --- a/src/main/java/org/wiremock/spring/internal/WireMockContextCustomizerFactory.java +++ b/src/main/java/org/wiremock/spring/internal/WireMockContextCustomizerFactory.java @@ -2,7 +2,11 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + import org.springframework.core.annotation.AnnotationUtils; import org.springframework.test.context.ContextConfigurationAttributes; import org.springframework.test.context.ContextCustomizer; @@ -12,65 +16,78 @@ import org.wiremock.spring.EnableWireMock; /** - * Creates {@link WireMockContextCustomizer} for test classes annotated with {@link EnableWireMock}. + * Creates {@link WireMockContextCustomizer} for test classes annotated with + * {@link EnableWireMock}. * * @author Maciej Walkowiak */ public class WireMockContextCustomizerFactory implements ContextCustomizerFactory { - static final ConfigureWireMock DEFAULT_CONFIGURE_WIREMOCK = - DefaultConfigureWireMock.class.getAnnotation(ConfigureWireMock.class); + static final ConfigureWireMock DEFAULT_CONFIGURE_WIREMOCK = DefaultConfigureWireMock.class + .getAnnotation(ConfigureWireMock.class); + + @ConfigureWireMock(name = "wiremock") + private static class DefaultConfigureWireMock { + } - @ConfigureWireMock(name = "wiremock") - private static class DefaultConfigureWireMock {} + static ConfigureWireMock[] getConfigureWireMocksOrDefault(final ConfigureWireMock... configureWireMock) { + if (configureWireMock == null || configureWireMock.length == 0) { + return new ConfigureWireMock[] { WireMockContextCustomizerFactory.DEFAULT_CONFIGURE_WIREMOCK }; + } + return configureWireMock; + } - static ConfigureWireMock[] getConfigureWireMocksOrDefault(final ConfigureWireMock... value) { - if (value == null || value.length == 0) { - return new ConfigureWireMock[] {WireMockContextCustomizerFactory.DEFAULT_CONFIGURE_WIREMOCK}; - } - return value; - } + @Override + public ContextCustomizer createContextCustomizer(final Class testClass, + final List configAttributes) { + // scan class and all enclosing classes if the test class is @Nested + final ConfigureWiremockHolder holder = new ConfigureWiremockHolder(); + this.parseDefinitions(testClass, holder); - @Override - public ContextCustomizer createContextCustomizer( - final Class testClass, final List configAttributes) { - // scan class and all enclosing classes if the test class is @Nested - final ConfigureWiremockHolder holder = new ConfigureWiremockHolder(); - this.parseDefinitions(testClass, holder); + if (holder.isEmpty()) { + return null; + } else { + return new WireMockContextCustomizer(holder.asArray()); + } + } - if (holder.isEmpty()) { - return null; - } else { - return new WireMockContextCustomizer(holder.asArray()); - } - } + private void parseDefinitions(final Class testClass, final ConfigureWiremockHolder parser) { + parser.parse(testClass); + if (TestContextAnnotationUtils.searchEnclosingClass(testClass)) { + this.parseDefinitions(testClass.getEnclosingClass(), parser); + } + } - private void parseDefinitions(final Class testClass, final ConfigureWiremockHolder parser) { - parser.parse(testClass); - if (TestContextAnnotationUtils.searchEnclosingClass(testClass)) { - this.parseDefinitions(testClass.getEnclosingClass(), parser); - } - } + private static class ConfigureWiremockHolder { + private final List annotations = new ArrayList<>(); - private static class ConfigureWiremockHolder { - private final List annotations = new ArrayList<>(); + void add(final ConfigureWireMock... annotations) { + this.annotations.addAll(Arrays.asList(annotations)); + this.sanityCheckDuplicateNames(this.annotations); + } - void add(final ConfigureWireMock... annotations) { - this.annotations.addAll(Arrays.asList(annotations)); - } + void parse(final Class clazz) { + final EnableWireMock annotation = AnnotationUtils.findAnnotation(clazz, EnableWireMock.class); + if (annotation != null) { + this.add(getConfigureWireMocksOrDefault(annotation.value())); + } + } - void parse(final Class clazz) { - final EnableWireMock annotation = AnnotationUtils.findAnnotation(clazz, EnableWireMock.class); - if (annotation != null) { - this.add(getConfigureWireMocksOrDefault(annotation.value())); - } - } + private void sanityCheckDuplicateNames(final List check) { + final List names = check.stream().map(it -> it.name()).toList(); + final Set dublicateNames = names.stream().filter(it -> Collections.frequency(names, it) > 1) + .collect(Collectors.toSet()); + if (!dublicateNames.isEmpty()) { + throw new IllegalStateException("Names of mocks must be unique, found duplicates of: " + + dublicateNames.stream().sorted().collect(Collectors.joining(","))); + } + } - boolean isEmpty() { - return this.annotations.isEmpty(); - } + boolean isEmpty() { + return this.annotations.isEmpty(); + } - ConfigureWireMock[] asArray() { - return this.annotations.toArray(new ConfigureWireMock[] {}); - } - } + ConfigureWireMock[] asArray() { + return this.annotations.toArray(new ConfigureWireMock[] {}); + } + } } diff --git a/src/test/java/org/wiremock/spring/test/ConfigurationValidationTest.java b/src/test/java/org/wiremock/spring/test/ConfigurationValidationTest.java new file mode 100644 index 0000000..e06c139 --- /dev/null +++ b/src/test/java/org/wiremock/spring/test/ConfigurationValidationTest.java @@ -0,0 +1,37 @@ +package org.wiremock.spring.test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertThrows; + +import org.junit.jupiter.api.Test; +import org.wiremock.spring.ConfigureWireMock; +import org.wiremock.spring.EnableWireMock; +import org.wiremock.spring.internal.WireMockContextCustomizerFactory; + +class ConfigurationValidationTest { + + @EnableWireMock({ @ConfigureWireMock, @ConfigureWireMock }) + private static class EnableWireMockSameDefaultName { + } + + @EnableWireMock({ @ConfigureWireMock(name = "w1"), @ConfigureWireMock(name = "w1") }) + private static class EnableWireMockSameGivenName { + } + + @Test + void testDuplicateNames_default() { + final IllegalStateException thrown = assertThrows(IllegalStateException.class, + () -> new WireMockContextCustomizerFactory() + .createContextCustomizer(EnableWireMockSameDefaultName.class, null)); + assertThat(thrown.getMessage()).isEqualTo("Names of mocks must be unique, found duplicates of: wiremock"); + } + + @Test + void testDuplicateNames_given() { + final IllegalStateException thrown = assertThrows(IllegalStateException.class, + () -> new WireMockContextCustomizerFactory().createContextCustomizer(EnableWireMockSameGivenName.class, + null)); + assertThat(thrown.getMessage()).isEqualTo("Names of mocks must be unique, found duplicates of: w1"); + } + +}