From a4104ab096b4a1f3f41995dec435b8435dc5473c Mon Sep 17 00:00:00 2001 From: Dmytro Nosan Date: Wed, 19 Jun 2019 17:48:38 +0300 Subject: [PATCH 1/2] Add @WebServiceClientTest slice test support Add `@WebServiceClientTest` and related test auto-configuration to allow slice testing of Spring Web Service client applications. See gh-17274 --- .../build.gradle | 2 + .../AutoConfigureMockWebServiceServer.java | 52 +++++++ .../client/AutoConfigureWebServiceClient.java | 54 ++++++++ ...MockWebServiceServerAutoConfiguration.java | 50 +++++++ ...WebServiceServerTestExecutionListener.java | 60 ++++++++ ...iceServerWebServiceTemplateCustomizer.java | 53 +++++++ .../client/TestMockWebServiceServer.java | 41 ++++++ .../client/WebServiceClientExcludeFilter.java | 47 +++++++ ...erviceClientTemplateAutoConfiguration.java | 49 +++++++ .../client/WebServiceClientTest.java | 129 ++++++++++++++++++ ...bServiceClientTestContextBootstrapper.java | 38 ++++++ .../webservices/client/package-info.java | 20 +++ .../main/resources/META-INF/spring.factories | 12 +- ...bServiceServerEnabledIntegrationTests.java | 47 +++++++ ...entWebServiceTemplateIntegrationTests.java | 61 +++++++++ .../client/ExampleWebServiceClient.java | 41 ++++++ .../ExampleWebServiceClientApplication.java | 32 +++++ .../webservices/client/Request.java | 29 ++++ .../webservices/client/Response.java | 38 ++++++ .../WebServiceClientIntegrationTests.java | 69 ++++++++++ ...viceClientNoComponentIntegrationTests.java | 64 +++++++++ ...rviceClientPropertiesIntegrationTests.java | 43 ++++++ .../WebServiceMarshallerConfiguration.java | 51 +++++++ 23 files changed, 1081 insertions(+), 1 deletion(-) create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureMockWebServiceServer.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureWebServiceClient.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerAutoConfiguration.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerTestExecutionListener.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerWebServiceTemplateCustomizer.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/TestMockWebServiceServer.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientExcludeFilter.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientTemplateAutoConfiguration.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientTest.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientTestContextBootstrapper.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/package-info.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureMockWebServiceServerEnabledIntegrationTests.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureWebServiceClientWebServiceTemplateIntegrationTests.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/ExampleWebServiceClient.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/ExampleWebServiceClientApplication.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/Request.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/Response.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientIntegrationTests.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientNoComponentIntegrationTests.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientPropertiesIntegrationTests.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceMarshallerConfiguration.java diff --git a/spring-boot-project/spring-boot-test-autoconfigure/build.gradle b/spring-boot-project/spring-boot-test-autoconfigure/build.gradle index 855e388468..2030b18a07 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-test-autoconfigure/build.gradle @@ -45,6 +45,8 @@ dependencies { optional("org.springframework.restdocs:spring-restdocs-webtestclient") optional("org.springframework.security:spring-security-config") optional("org.springframework.security:spring-security-test") + optional("org.springframework.ws:spring-ws-core") + optional("org.springframework.ws:spring-ws-test") optional("org.apache.tomcat.embed:tomcat-embed-core") optional("org.mongodb:mongodb-driver-reactivestreams") optional("org.mongodb:mongodb-driver-sync") diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureMockWebServiceServer.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureMockWebServiceServer.java new file mode 100644 index 0000000000..7220f6bad5 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureMockWebServiceServer.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.autoconfigure.properties.PropertyMapping; +import org.springframework.ws.test.client.MockWebServiceServer; + +/** + * Annotation that can be applied to a test class to enable and configure + * auto-configuration of a single {@link MockWebServiceServer}. + * + * @author Dmytro Nosan + * @since 2.3.0 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@ImportAutoConfiguration +@PropertyMapping("spring.test.webservice.client.mock-server") +public @interface AutoConfigureMockWebServiceServer { + + /** + * If {@link MockWebServiceServer} bean should be registered. Defaults to + * {@code true}. + * @return if mock support is enabled + */ + boolean enabled() default true; + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureWebServiceClient.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureWebServiceClient.java new file mode 100644 index 0000000000..11cddd90c8 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureWebServiceClient.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.autoconfigure.properties.PropertyMapping; +import org.springframework.boot.webservices.client.WebServiceTemplateBuilder; +import org.springframework.ws.client.core.WebServiceTemplate; + +/** + * Annotation that can be applied to a test class to enable and configure + * auto-configuration of web service clients. + * + * @author Dmytro Nosan + * @since 2.3.0 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@ImportAutoConfiguration +@PropertyMapping("spring.test.webservice.client") +public @interface AutoConfigureWebServiceClient { + + /** + * If a {@link WebServiceTemplate} bean should be registered. Defaults to + * {@code false} with the assumption that the {@link WebServiceTemplateBuilder} will + * be used. + * @return if a {@link WebServiceTemplate} bean should be added. + */ + boolean registerWebServiceTemplate() default false; + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerAutoConfiguration.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerAutoConfiguration.java new file mode 100644 index 0000000000..f6e5f75cdb --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerAutoConfiguration.java @@ -0,0 +1,50 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.ws.client.core.WebServiceTemplate; +import org.springframework.ws.test.client.MockWebServiceMessageSender; +import org.springframework.ws.test.client.MockWebServiceServer; + +/** + * Auto-configuration for {@link MockWebServiceServer} support. + * + * @author Dmytro Nosan + * @see AutoConfigureMockWebServiceServer + * @since 2.3.0 + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnProperty(prefix = "spring.test.webservice.client.mock-server", name = "enabled") +@ConditionalOnClass({ MockWebServiceServer.class, WebServiceTemplate.class }) +public class MockWebServiceServerAutoConfiguration { + + @Bean + public TestMockWebServiceServer mockWebServiceServer() { + return new TestMockWebServiceServer(new MockWebServiceMessageSender()); + } + + @Bean + public MockWebServiceServerWebServiceTemplateCustomizer mockWebServiceServerWebServiceTemplateCustomizer( + TestMockWebServiceServer mockWebServiceServer) { + return new MockWebServiceServerWebServiceTemplateCustomizer(mockWebServiceServer); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerTestExecutionListener.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerTestExecutionListener.java new file mode 100644 index 0000000000..6e65ea6551 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerTestExecutionListener.java @@ -0,0 +1,60 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.springframework.context.ApplicationContext; +import org.springframework.core.Ordered; +import org.springframework.test.context.TestContext; +import org.springframework.test.context.TestExecutionListener; +import org.springframework.test.context.support.AbstractTestExecutionListener; +import org.springframework.util.ClassUtils; +import org.springframework.ws.test.client.MockWebServiceServer; + +/** + * {@link TestExecutionListener} to {@code verify} and {@code reset} + * {@link MockWebServiceServer}. + * + * @author Dmytro Nosan + * @since 2.3.0 + */ +public class MockWebServiceServerTestExecutionListener extends AbstractTestExecutionListener { + + private static final String MOCK_SERVER_CLASS = "org.springframework.ws.test.client.MockWebServiceServer"; + + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE - 100; + } + + @Override + public void afterTestMethod(TestContext testContext) { + if (isMockWebServiceServerPresent()) { + ApplicationContext applicationContext = testContext.getApplicationContext(); + String[] names = applicationContext.getBeanNamesForType(MockWebServiceServer.class, false, false); + for (String name : names) { + MockWebServiceServer mockServer = applicationContext.getBean(name, MockWebServiceServer.class); + mockServer.verify(); + mockServer.reset(); + } + } + } + + private boolean isMockWebServiceServerPresent() { + return ClassUtils.isPresent(MOCK_SERVER_CLASS, getClass().getClassLoader()); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerWebServiceTemplateCustomizer.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerWebServiceTemplateCustomizer.java new file mode 100644 index 0000000000..ddaa66ff66 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerWebServiceTemplateCustomizer.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.springframework.boot.webservices.client.WebServiceTemplateBuilder; +import org.springframework.boot.webservices.client.WebServiceTemplateCustomizer; +import org.springframework.ws.client.core.WebServiceTemplate; +import org.springframework.ws.test.client.MockWebServiceServer; + +/** + * {@link WebServiceTemplateCustomizer} that can be applied to a + * {@link WebServiceTemplateBuilder} instances to add {@link MockWebServiceServer} + * support. + * + * @author Dmytro Nosan + */ +class MockWebServiceServerWebServiceTemplateCustomizer implements WebServiceTemplateCustomizer { + + private final AtomicBoolean alreadySet = new AtomicBoolean(); + + private final TestMockWebServiceServer mockServer; + + MockWebServiceServerWebServiceTemplateCustomizer(TestMockWebServiceServer mockServer) { + this.mockServer = mockServer; + } + + @Override + public void customize(WebServiceTemplate webServiceTemplate) { + if (this.alreadySet.compareAndSet(false, true)) { + webServiceTemplate.setMessageSender(this.mockServer.getMockMessageSender()); + } + else { + throw new IllegalStateException("@WebServiceClientTest supports only a single WebServiceTemplate"); + } + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/TestMockWebServiceServer.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/TestMockWebServiceServer.java new file mode 100644 index 0000000000..be76a76e4c --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/TestMockWebServiceServer.java @@ -0,0 +1,41 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.springframework.ws.test.client.MockWebServiceMessageSender; +import org.springframework.ws.test.client.MockWebServiceServer; + +/** + * Test {@link MockWebServiceServer} which provides access to the underlying + * {@link MockWebServiceMessageSender}. + * + * @author Dmytro Nosan + */ +final class TestMockWebServiceServer extends MockWebServiceServer { + + private final MockWebServiceMessageSender mockMessageSender; + + TestMockWebServiceServer(MockWebServiceMessageSender mockMessageSender) { + super(mockMessageSender); + this.mockMessageSender = mockMessageSender; + } + + MockWebServiceMessageSender getMockMessageSender() { + return this.mockMessageSender; + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientExcludeFilter.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientExcludeFilter.java new file mode 100644 index 0000000000..684dfd34c8 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientExcludeFilter.java @@ -0,0 +1,47 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.springframework.boot.context.TypeExcludeFilter; +import org.springframework.boot.test.autoconfigure.filter.StandardAnnotationCustomizableTypeExcludeFilter; + +/** + * {@link TypeExcludeFilter} for {@link WebServiceClientTest @WebServiceClientTest}. + * + * @author Dmytro Nosan + * @since 2.3.0 + */ +public final class WebServiceClientExcludeFilter + extends StandardAnnotationCustomizableTypeExcludeFilter { + + private final Class[] components; + + protected WebServiceClientExcludeFilter(Class testClass) { + super(testClass); + this.components = getAnnotation().getValue("components", Class[].class).orElse(new Class[0]); + } + + @Override + protected Set> getComponentIncludes() { + return new LinkedHashSet<>(Arrays.asList(this.components)); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientTemplateAutoConfiguration.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientTemplateAutoConfiguration.java new file mode 100644 index 0000000000..8dfd08cc1a --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientTemplateAutoConfiguration.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration; +import org.springframework.boot.webservices.client.WebServiceTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.ws.client.core.WebServiceTemplate; + +/** + * Auto-configuration for a web-client {@link WebServiceTemplate}. Used when + * {@link AutoConfigureWebServiceClient#registerWebServiceTemplate()} is {@code true}. + * + * @author Dmytro Nosan + * @since 2.3.0 + * @see AutoConfigureWebServiceClient + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnProperty(prefix = "spring.test.webservice.client", name = "register-web-service-template") +@AutoConfigureAfter(WebServiceTemplateAutoConfiguration.class) +@ConditionalOnClass(WebServiceTemplate.class) +@ConditionalOnBean(WebServiceTemplateBuilder.class) +public class WebServiceClientTemplateAutoConfiguration { + + @Bean + public WebServiceTemplate webServiceTemplate(WebServiceTemplateBuilder builder) { + return builder.build(); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientTest.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientTest.java new file mode 100644 index 0000000000..8b67297401 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientTest.java @@ -0,0 +1,129 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.extension.ExtendWith; + +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration; +import org.springframework.boot.test.autoconfigure.core.AutoConfigureCache; +import org.springframework.boot.test.autoconfigure.filter.TypeExcludeFilters; +import org.springframework.boot.webservices.client.WebServiceTemplateBuilder; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.core.annotation.AliasFor; +import org.springframework.core.env.Environment; +import org.springframework.test.context.BootstrapWith; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.ws.client.core.WebServiceTemplate; +import org.springframework.ws.test.client.MockWebServiceServer; + +/** + * Annotation that can be used for a typical Spring web service client test. Can be used + * when a test focuses only on beans that use + * {@link WebServiceTemplateBuilder}. By default, tests annotated with + * {@code WebServiceClientTest} will also auto-configure a {@link MockWebServiceServer}. + *

+ * If you are testing a bean that doesn't use {@link WebServiceTemplateBuilder} but + * instead injects a {@link WebServiceTemplate} directly, you can add + * {@code @AutoConfigureWebServiceClient(registerWebServiceTemplate=true)}. + *

+ * When using JUnit 4, this annotation should be used in combination with + * {@code @RunWith(SpringRunner.class)}. + * + * @author Dmytro Nosan + * @since 2.3.0 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@BootstrapWith(WebServiceClientTestContextBootstrapper.class) +@ExtendWith(SpringExtension.class) +@OverrideAutoConfiguration(enabled = false) +@TypeExcludeFilters(WebServiceClientExcludeFilter.class) +@AutoConfigureCache +@AutoConfigureMockWebServiceServer +@AutoConfigureWebServiceClient +@ImportAutoConfiguration +public @interface WebServiceClientTest { + + /** + * Properties in form {@literal key=value} that should be added to the Spring + * {@link Environment} before the test runs. + * @return the properties to add + */ + String[] properties() default {}; + + /** + * Specifies the components to test. This is an alias of {@link #components()} which + * can be used for brevity if no other attributes are defined. See + * {@link #components()} for details. + * @see #components() + * @return the components to test + */ + @AliasFor("components") + Class[] value() default {}; + + /** + * Specifies the components to test. May be left blank if components will be manually + * imported or created directly. + * @see #value() + * @return the components to test + */ + @AliasFor("value") + Class[] components() default {}; + + /** + * Determines if default filtering should be used with + * {@link SpringBootApplication @SpringBootApplication}. By default only + * {@code @JsonComponent} and {@code Module} beans are included. + * @see #includeFilters() + * @see #excludeFilters() + * @return if default filters should be used + */ + boolean useDefaultFilters() default true; + + /** + * A set of include filters which can be used to add otherwise filtered beans to the + * application context. + * @return include filters to apply + */ + ComponentScan.Filter[] includeFilters() default {}; + + /** + * A set of exclude filters which can be used to filter beans that would otherwise be + * added to the application context. + * @return exclude filters to apply + */ + ComponentScan.Filter[] excludeFilters() default {}; + + /** + * Auto-configuration exclusions that should be applied for this test. + * @return auto-configuration exclusions to apply + */ + @AliasFor(annotation = ImportAutoConfiguration.class, attribute = "exclude") + Class[] excludeAutoConfiguration() default {}; + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientTestContextBootstrapper.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientTestContextBootstrapper.java new file mode 100644 index 0000000000..d3d4bc0132 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientTestContextBootstrapper.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.springframework.boot.test.context.SpringBootTestContextBootstrapper; +import org.springframework.core.annotation.MergedAnnotations; +import org.springframework.core.annotation.MergedAnnotations.SearchStrategy; +import org.springframework.test.context.TestContextBootstrapper; + +/** + * {@link TestContextBootstrapper} for {@link WebServiceClientTest @WebServiceClientTest} + * support. + * + * @author Dmytro Nosan + */ +class WebServiceClientTestContextBootstrapper extends SpringBootTestContextBootstrapper { + + @Override + protected String[] getProperties(Class testClass) { + return MergedAnnotations.from(testClass, SearchStrategy.INHERITED_ANNOTATIONS).get(WebServiceClientTest.class) + .getValue("properties", String[].class).orElse(null); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/package-info.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/package-info.java new file mode 100644 index 0000000000..cca66f26b3 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Auto-configuration for web service clients. + */ +package org.springframework.boot.test.autoconfigure.webservices.client; diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories index ba8859956e..b8e2f732f2 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories @@ -168,6 +168,15 @@ org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration +# AutoConfigureWebServiceClient +org.springframework.boot.test.autoconfigure.webservices.client.AutoConfigureWebServiceClient=\ +org.springframework.boot.test.autoconfigure.webservices.client.WebServiceClientTemplateAutoConfiguration,\ +org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration + +# AutoConfigureMockWebServiceServer +org.springframework.boot.test.autoconfigure.webservices.client.AutoConfigureMockWebServiceServer=\ +org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerAutoConfiguration + # DefaultTestExecutionListenersPostProcessors org.springframework.boot.test.context.DefaultTestExecutionListenersPostProcessor=\ org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener$PostProcessor @@ -184,4 +193,5 @@ org.springframework.test.context.TestExecutionListener=\ org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener,\ org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener,\ org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener,\ -org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener +org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener,\ +org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureMockWebServiceServerEnabledIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureMockWebServiceServerEnabledIntegrationTests.java new file mode 100644 index 0000000000..3c5b35930b --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureMockWebServiceServerEnabledIntegrationTests.java @@ -0,0 +1,47 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.ws.test.client.MockWebServiceServer; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +/** + * Tests for {@link AutoConfigureMockWebServiceServer @AutoConfigureMockWebServiceServer} + * with {@code enabled=false}. + * + * @author Dmytro Nosan + */ +@WebServiceClientTest +@AutoConfigureMockWebServiceServer(enabled = false) +class AutoConfigureMockWebServiceServerEnabledIntegrationTests { + + @Autowired + private ApplicationContext applicationContext; + + @Test + void mockWebServiceServerShouldNotBeRegistered() { + assertThatExceptionOfType(NoSuchBeanDefinitionException.class) + .isThrownBy(() -> this.applicationContext.getBean(MockWebServiceServer.class)); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureWebServiceClientWebServiceTemplateIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureWebServiceClientWebServiceTemplateIntegrationTests.java new file mode 100644 index 0000000000..56093c1ed2 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureWebServiceClientWebServiceTemplateIntegrationTests.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.ws.client.core.WebServiceTemplate; +import org.springframework.ws.test.client.MockWebServiceServer; +import org.springframework.ws.test.client.RequestMatchers; +import org.springframework.ws.test.client.ResponseCreators; +import org.springframework.xml.transform.StringSource; + +/** + * Tests for {@link AutoConfigureWebServiceClient @AutoConfigureWebServiceClient} with + * {@code registerWebServiceTemplate=true}. + * + * @author Dmytro Nosan + */ +@SpringBootTest +@AutoConfigureWebServiceClient(registerWebServiceTemplate = true) +@AutoConfigureMockWebServiceServer +class AutoConfigureWebServiceClientWebServiceTemplateIntegrationTests { + + @Autowired + private WebServiceTemplate webServiceTemplate; + + @Autowired + private MockWebServiceServer mockWebServiceServer; + + @Test + void webServiceTemplateTest() { + this.mockWebServiceServer.expect(RequestMatchers.payload(new StringSource(""))) + .andRespond(ResponseCreators.withPayload(new StringSource(""))); + this.webServiceTemplate.marshalSendAndReceive("https://example.com", new Request()); + } + + @Configuration(proxyBeanMethods = false) + @Import(WebServiceMarshallerConfiguration.class) + static class Config { + + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/ExampleWebServiceClient.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/ExampleWebServiceClient.java new file mode 100644 index 0000000000..96b172d0fd --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/ExampleWebServiceClient.java @@ -0,0 +1,41 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.springframework.boot.webservices.client.WebServiceTemplateBuilder; +import org.springframework.stereotype.Service; +import org.springframework.ws.client.core.WebServiceTemplate; + +/** + * Example web client used with {@link WebServiceClientTest @WebServiceClientTest} tests. + * + * @author Dmytro Nosan + */ +@Service +public class ExampleWebServiceClient { + + private WebServiceTemplate webServiceTemplate; + + public ExampleWebServiceClient(WebServiceTemplateBuilder builder) { + this.webServiceTemplate = builder.build(); + } + + public Response test() { + return (Response) this.webServiceTemplate.marshalSendAndReceive("https://example.com", new Request()); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/ExampleWebServiceClientApplication.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/ExampleWebServiceClientApplication.java new file mode 100644 index 0000000000..7e74b64ba5 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/ExampleWebServiceClientApplication.java @@ -0,0 +1,32 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Import; + +/** + * Example {@link SpringBootApplication @SpringBootApplication} used with + * {@link WebServiceClientTest @WebServiceClientTest} tests. + * + * @author Dmytro Nosan + */ +@SpringBootApplication +@Import(WebServiceMarshallerConfiguration.class) +public class ExampleWebServiceClientApplication { + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/Request.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/Request.java new file mode 100644 index 0000000000..8fead68404 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/Request.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Test request. + * + * @author Dmytro Nosan + */ +@XmlRootElement(name = "request") +class Request { + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/Response.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/Response.java new file mode 100644 index 0000000000..82e5f923e8 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/Response.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Test response. + * + * @author Dmytro Nosan + */ +@XmlRootElement(name = "response") +@XmlAccessorType(XmlAccessType.FIELD) +class Response { + + private int status; + + int getStatus() { + return this.status; + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientIntegrationTests.java new file mode 100644 index 0000000000..ef28d34e66 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientIntegrationTests.java @@ -0,0 +1,69 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ws.client.WebServiceTransportException; +import org.springframework.ws.test.client.MockWebServiceServer; +import org.springframework.ws.test.client.RequestMatchers; +import org.springframework.ws.test.client.ResponseCreators; +import org.springframework.ws.test.support.SourceAssertionError; +import org.springframework.xml.transform.StringSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +/** + * Tests for {@link WebServiceClientTest @WebServiceClientTest}. + * + * @author Dmytro Nosan + */ +@WebServiceClientTest(ExampleWebServiceClient.class) +class WebServiceClientIntegrationTests { + + @Autowired + private MockWebServiceServer mockWebServiceServer; + + @Autowired + private ExampleWebServiceClient client; + + @Test + void mockServerCall() { + this.mockWebServiceServer.expect(RequestMatchers.payload(new StringSource(""))).andRespond( + ResponseCreators.withPayload(new StringSource("200"))); + assertThat(this.client.test()).extracting(Response::getStatus).isEqualTo(200); + } + + @Test + void mockServerCall1() { + this.mockWebServiceServer.expect(RequestMatchers.connectionTo("https://example1")) + .andRespond(ResponseCreators.withPayload(new StringSource(""))); + assertThatExceptionOfType(SourceAssertionError.class).isThrownBy(this.client::test) + .withMessageContaining("Unexpected connection expected"); + } + + @Test + void mockServerCall2() { + this.mockWebServiceServer.expect(RequestMatchers.payload(new StringSource(""))) + .andRespond(ResponseCreators.withError("Invalid Request")); + assertThatExceptionOfType(WebServiceTransportException.class).isThrownBy(this.client::test) + .withMessageContaining("Invalid Request"); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientNoComponentIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientNoComponentIntegrationTests.java new file mode 100644 index 0000000000..7d76b7d3cb --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientNoComponentIntegrationTests.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webservices.client.WebServiceTemplateBuilder; +import org.springframework.context.ApplicationContext; +import org.springframework.ws.test.client.MockWebServiceServer; +import org.springframework.ws.test.client.RequestMatchers; +import org.springframework.ws.test.client.ResponseCreators; +import org.springframework.xml.transform.StringSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +/** + * Tests for {@link WebServiceClientTest @WebServiceClientTest} with no specific client. + * + * @author Dmytro Nosan + */ +@WebServiceClientTest +class WebServiceClientNoComponentIntegrationTests { + + @Autowired + private ApplicationContext applicationContext; + + @Autowired + private WebServiceTemplateBuilder webServiceTemplateBuilder; + + @Autowired + private MockWebServiceServer mockWebServiceServer; + + @Test + void exampleClientIsNotInjected() { + assertThatExceptionOfType(NoSuchBeanDefinitionException.class) + .isThrownBy(() -> this.applicationContext.getBean(ExampleWebServiceClient.class)); + } + + @Test + void manuallyCreateBean() { + ExampleWebServiceClient client = new ExampleWebServiceClient(this.webServiceTemplateBuilder); + this.mockWebServiceServer.expect(RequestMatchers.payload(new StringSource(""))).andRespond( + ResponseCreators.withPayload(new StringSource("200"))); + assertThat(client.test()).extracting(Response::getStatus).isEqualTo(200); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientPropertiesIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientPropertiesIntegrationTests.java new file mode 100644 index 0000000000..b1d01217ac --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientPropertiesIntegrationTests.java @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for the {@link WebServiceClientTest#properties properties} attribute of + * {@link WebServiceClientTest @WebServiceClientTest}. + * + * @author Dmytro Nosan + */ +@WebServiceClientTest(properties = "spring.profiles.active=test") +class WebServiceClientPropertiesIntegrationTests { + + @Autowired + private Environment environment; + + @Test + void environmentWithNewProfile() { + assertThat(this.environment.getActiveProfiles()).containsExactly("test"); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceMarshallerConfiguration.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceMarshallerConfiguration.java new file mode 100644 index 0000000000..559407b959 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceMarshallerConfiguration.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.autoconfigure.webservices.client; + +import org.springframework.boot.webservices.client.WebServiceTemplateCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.Unmarshaller; +import org.springframework.oxm.jaxb.Jaxb2Marshaller; + +/** + * Test configuration to configure {@code Marshaller} and {@code Unmarshaller}. + * + * @author Dmytro Nosan + */ +@Configuration(proxyBeanMethods = false) +class WebServiceMarshallerConfiguration { + + @Bean + WebServiceTemplateCustomizer marshallerCustomizer(Marshaller marshaller) { + return (webServiceTemplate) -> webServiceTemplate.setMarshaller(marshaller); + } + + @Bean + WebServiceTemplateCustomizer unmarshallerCustomizer(Unmarshaller unmarshaller) { + return (webServiceTemplate) -> webServiceTemplate.setUnmarshaller(unmarshaller); + } + + @Bean + Jaxb2Marshaller createJaxbMarshaller() { + Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller(); + jaxb2Marshaller.setClassesToBeBound(Request.class, Response.class); + return jaxb2Marshaller; + } + +} From 194c9fac64a48dd612bf17ebd052bdfd45cbde97 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 13 May 2020 21:01:36 -0700 Subject: [PATCH 2/2] Polish 'Add @WebServiceClientTest slice test support' See gh-17274 --- .../docs/asciidoc/spring-boot-features.adoc | 34 +++++++++++++++++++ .../AutoConfigureMockWebServiceServer.java | 2 +- ...MockWebServiceServerAutoConfiguration.java | 2 +- ...iceServerWebServiceTemplateCustomizer.java | 11 +++--- ...entWebServiceTemplateIntegrationTests.java | 11 +++--- .../WebServiceClientIntegrationTests.java | 18 +++++----- ...viceClientNoComponentIntegrationTests.java | 10 +++--- 7 files changed, 60 insertions(+), 28 deletions(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc index 683f1a0b6b..beb8d41a4e 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc @@ -7284,6 +7284,40 @@ include::{code-examples}/test/autoconfigure/restdocs/restassured/AdvancedConfigu +[[boot-features-testing-spring-boot-applications-testing-autoconfigured-webservices]] +==== Auto-configured Spring Web Services Tests +You can use `@WebServiceClientTest` to test applications that use call web services using the Spring Web Services project. +By default, it configures a mock `WebServiceServer` bean and automatically customizes your `WebServiceTemplateBuilder`. +(For more about using Web Services with Spring Boot, see "<>", earlier in this chapter.) + + +TIP: A list of the auto-configuration settings that are enabled by `@WebServiceClientTest` can be <>. + +The following example shows the `@WebServiceClientTest` annotation in use: + +[source,java,indent=0] +---- + @WebServiceClientTest(ExampleWebServiceClient.class) + class WebServiceClientIntegrationTests { + + @Autowired + private MockWebServiceServer server; + + @Autowired + private ExampleWebServiceClient client; + + @Test + void mockServerCall() { + this.server.expect(payload(new StringSource(""))).andRespond( + withPayload(new StringSource("200"))); + assertThat(this.client.test()).extracting(Response::getStatus).isEqualTo(200); + } + + } +---- + + + [[boot-features-testing-spring-boot-applications-testing-auto-configured-additional-auto-config]] ==== Additional Auto-configuration and Slicing Each slice provides one or more `@AutoConfigure...` annotations that namely defines the auto-configurations that should be included as part of a slice. diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureMockWebServiceServer.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureMockWebServiceServer.java index 7220f6bad5..0ab829870c 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureMockWebServiceServer.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureMockWebServiceServer.java @@ -39,7 +39,7 @@ import org.springframework.ws.test.client.MockWebServiceServer; @Documented @Inherited @ImportAutoConfiguration -@PropertyMapping("spring.test.webservice.client.mock-server") +@PropertyMapping("spring.test.webservice.client.mockserver") public @interface AutoConfigureMockWebServiceServer { /** diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerAutoConfiguration.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerAutoConfiguration.java index f6e5f75cdb..693d7de2bf 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerAutoConfiguration.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerAutoConfiguration.java @@ -32,7 +32,7 @@ import org.springframework.ws.test.client.MockWebServiceServer; * @since 2.3.0 */ @Configuration(proxyBeanMethods = false) -@ConditionalOnProperty(prefix = "spring.test.webservice.client.mock-server", name = "enabled") +@ConditionalOnProperty(prefix = "spring.test.webservice.client.mockserver", name = "enabled") @ConditionalOnClass({ MockWebServiceServer.class, WebServiceTemplate.class }) public class MockWebServiceServerAutoConfiguration { diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerWebServiceTemplateCustomizer.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerWebServiceTemplateCustomizer.java index ddaa66ff66..1edb211887 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerWebServiceTemplateCustomizer.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/webservices/client/MockWebServiceServerWebServiceTemplateCustomizer.java @@ -20,6 +20,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.springframework.boot.webservices.client.WebServiceTemplateBuilder; import org.springframework.boot.webservices.client.WebServiceTemplateCustomizer; +import org.springframework.util.Assert; import org.springframework.ws.client.core.WebServiceTemplate; import org.springframework.ws.test.client.MockWebServiceServer; @@ -32,7 +33,7 @@ import org.springframework.ws.test.client.MockWebServiceServer; */ class MockWebServiceServerWebServiceTemplateCustomizer implements WebServiceTemplateCustomizer { - private final AtomicBoolean alreadySet = new AtomicBoolean(); + private final AtomicBoolean applied = new AtomicBoolean(); private final TestMockWebServiceServer mockServer; @@ -42,12 +43,8 @@ class MockWebServiceServerWebServiceTemplateCustomizer implements WebServiceTemp @Override public void customize(WebServiceTemplate webServiceTemplate) { - if (this.alreadySet.compareAndSet(false, true)) { - webServiceTemplate.setMessageSender(this.mockServer.getMockMessageSender()); - } - else { - throw new IllegalStateException("@WebServiceClientTest supports only a single WebServiceTemplate"); - } + Assert.state(!this.applied.getAndSet(true), "@WebServiceClientTest supports only a single WebServiceTemplate"); + webServiceTemplate.setMessageSender(this.mockServer.getMockMessageSender()); } } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureWebServiceClientWebServiceTemplateIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureWebServiceClientWebServiceTemplateIntegrationTests.java index 56093c1ed2..bd7f5c2355 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureWebServiceClientWebServiceTemplateIntegrationTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/AutoConfigureWebServiceClientWebServiceTemplateIntegrationTests.java @@ -24,10 +24,11 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.ws.client.core.WebServiceTemplate; import org.springframework.ws.test.client.MockWebServiceServer; -import org.springframework.ws.test.client.RequestMatchers; -import org.springframework.ws.test.client.ResponseCreators; import org.springframework.xml.transform.StringSource; +import static org.springframework.ws.test.client.RequestMatchers.payload; +import static org.springframework.ws.test.client.ResponseCreators.withPayload; + /** * Tests for {@link AutoConfigureWebServiceClient @AutoConfigureWebServiceClient} with * {@code registerWebServiceTemplate=true}. @@ -43,12 +44,12 @@ class AutoConfigureWebServiceClientWebServiceTemplateIntegrationTests { private WebServiceTemplate webServiceTemplate; @Autowired - private MockWebServiceServer mockWebServiceServer; + private MockWebServiceServer server; @Test void webServiceTemplateTest() { - this.mockWebServiceServer.expect(RequestMatchers.payload(new StringSource(""))) - .andRespond(ResponseCreators.withPayload(new StringSource(""))); + this.server.expect(payload(new StringSource(""))) + .andRespond(withPayload(new StringSource(""))); this.webServiceTemplate.marshalSendAndReceive("https://example.com", new Request()); } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientIntegrationTests.java index ef28d34e66..2cb674e1cd 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientIntegrationTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientIntegrationTests.java @@ -21,13 +21,15 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ws.client.WebServiceTransportException; import org.springframework.ws.test.client.MockWebServiceServer; -import org.springframework.ws.test.client.RequestMatchers; -import org.springframework.ws.test.client.ResponseCreators; import org.springframework.ws.test.support.SourceAssertionError; import org.springframework.xml.transform.StringSource; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.springframework.ws.test.client.RequestMatchers.connectionTo; +import static org.springframework.ws.test.client.RequestMatchers.payload; +import static org.springframework.ws.test.client.ResponseCreators.withError; +import static org.springframework.ws.test.client.ResponseCreators.withPayload; /** * Tests for {@link WebServiceClientTest @WebServiceClientTest}. @@ -38,30 +40,28 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; class WebServiceClientIntegrationTests { @Autowired - private MockWebServiceServer mockWebServiceServer; + private MockWebServiceServer server; @Autowired private ExampleWebServiceClient client; @Test void mockServerCall() { - this.mockWebServiceServer.expect(RequestMatchers.payload(new StringSource(""))).andRespond( - ResponseCreators.withPayload(new StringSource("200"))); + this.server.expect(payload(new StringSource(""))) + .andRespond(withPayload(new StringSource("200"))); assertThat(this.client.test()).extracting(Response::getStatus).isEqualTo(200); } @Test void mockServerCall1() { - this.mockWebServiceServer.expect(RequestMatchers.connectionTo("https://example1")) - .andRespond(ResponseCreators.withPayload(new StringSource(""))); + this.server.expect(connectionTo("https://example1")).andRespond(withPayload(new StringSource(""))); assertThatExceptionOfType(SourceAssertionError.class).isThrownBy(this.client::test) .withMessageContaining("Unexpected connection expected"); } @Test void mockServerCall2() { - this.mockWebServiceServer.expect(RequestMatchers.payload(new StringSource(""))) - .andRespond(ResponseCreators.withError("Invalid Request")); + this.server.expect(payload(new StringSource(""))).andRespond(withError("Invalid Request")); assertThatExceptionOfType(WebServiceTransportException.class).isThrownBy(this.client::test) .withMessageContaining("Invalid Request"); } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientNoComponentIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientNoComponentIntegrationTests.java index 7d76b7d3cb..fdf01f2a13 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientNoComponentIntegrationTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/webservices/client/WebServiceClientNoComponentIntegrationTests.java @@ -23,12 +23,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.webservices.client.WebServiceTemplateBuilder; import org.springframework.context.ApplicationContext; import org.springframework.ws.test.client.MockWebServiceServer; -import org.springframework.ws.test.client.RequestMatchers; -import org.springframework.ws.test.client.ResponseCreators; import org.springframework.xml.transform.StringSource; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.springframework.ws.test.client.RequestMatchers.payload; +import static org.springframework.ws.test.client.ResponseCreators.withPayload; /** * Tests for {@link WebServiceClientTest @WebServiceClientTest} with no specific client. @@ -45,7 +45,7 @@ class WebServiceClientNoComponentIntegrationTests { private WebServiceTemplateBuilder webServiceTemplateBuilder; @Autowired - private MockWebServiceServer mockWebServiceServer; + private MockWebServiceServer server; @Test void exampleClientIsNotInjected() { @@ -56,8 +56,8 @@ class WebServiceClientNoComponentIntegrationTests { @Test void manuallyCreateBean() { ExampleWebServiceClient client = new ExampleWebServiceClient(this.webServiceTemplateBuilder); - this.mockWebServiceServer.expect(RequestMatchers.payload(new StringSource(""))).andRespond( - ResponseCreators.withPayload(new StringSource("200"))); + this.server.expect(payload(new StringSource(""))) + .andRespond(withPayload(new StringSource("200"))); assertThat(client.test()).extracting(Response::getStatus).isEqualTo(200); }