From 48aa8f763d180724cf73e892241ca9735fbfda85 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Mon, 22 Aug 2016 16:29:09 +0200 Subject: [PATCH] DiscoveryClient is optional without this change if you want to use Spring Cloud Contract Stub Runner Cloud you need to have an implementation of Service Discovery on your classpath. That's not always what you want to have - actually the tests should be possible to be run without any backing service disvoery technology. This change provides the default NoOp Discovery Client in case where there is no bean of DiscoveryClient type. fixes #56 --- pom.xml | 2 +- .../cloud/StubRunnerDiscoveryClient.java | 9 ++- ...tubRunnerSpringCloudAutoConfiguration.java | 12 ++- ...nerSpringCloudAutoConfigurationSpec.groovy | 10 +-- ...toConfigurationWithoutDiscoverySpec.groovy | 80 +++++++++++++++++++ 5 files changed, 103 insertions(+), 10 deletions(-) create mode 100644 spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationWithoutDiscoverySpec.groovy diff --git a/pom.xml b/pom.xml index 51049478d1..b9ad39a70d 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ 5.12.1 2.17.0 1.0.2.RELEASE - 1.4.0.RC1 + 1.4.0.RELEASE diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerDiscoveryClient.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerDiscoveryClient.java index eeff4e92d3..928197f402 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerDiscoveryClient.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerDiscoveryClient.java @@ -46,12 +46,19 @@ class StubRunnerDiscoveryClient implements DiscoveryClient { public StubRunnerDiscoveryClient(DiscoveryClient delegate, StubFinder stubFinder, StubMapperProperties stubMapperProperties, String springAppName) { - this.delegate = delegate instanceof StubRunnerDiscoveryClient ? + this.delegate = delegate instanceof StubRunnerDiscoveryClient ? noOpDiscoveryClient(springAppName) : delegate; this.stubFinder = stubFinder; this.stubMapperProperties = stubMapperProperties; } + public StubRunnerDiscoveryClient(StubFinder stubFinder, + StubMapperProperties stubMapperProperties, String springAppName) { + this.delegate = noOpDiscoveryClient(springAppName); + this.stubFinder = stubFinder; + this.stubMapperProperties = stubMapperProperties; + } + private NoopDiscoveryClient noOpDiscoveryClient(String springAppName) { return new NoopDiscoveryClient(new DefaultServiceInstance(springAppName, "localhost", 0, false)); } diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfiguration.java index 7c312a6e63..64bdef7d7c 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfiguration.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.cloud.contract.stubrunner.spring.cloud; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -46,12 +47,21 @@ public class StubRunnerSpringCloudAutoConfiguration { } @Bean + @ConditionalOnBean(DiscoveryClient.class) @Primary - public DiscoveryClient stubRunnerDiscoveryClient(DiscoveryClient discoveryClient, + public DiscoveryClient stubRunnerDiscoveryClientWrapper(DiscoveryClient discoveryClient, StubFinder stubFinder, StubMapperProperties stubMapperProperties, @Value("${spring.application.name:unknown}") String springAppName) { return new StubRunnerDiscoveryClient(discoveryClient, stubFinder, stubMapperProperties, springAppName); } + @Bean + @ConditionalOnMissingBean(DiscoveryClient.class) + public DiscoveryClient stubRunnerDiscoveryClient(StubFinder stubFinder, + StubMapperProperties stubMapperProperties, + @Value("${spring.application.name:unknown}") String springAppName) { + return new StubRunnerDiscoveryClient(stubFinder, stubMapperProperties, springAppName); + } + } diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationSpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationSpec.groovy index 7c0cd09da0..8af8d00144 100644 --- a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationSpec.groovy +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationSpec.groovy @@ -21,9 +21,8 @@ import org.junit.AfterClass import org.junit.BeforeClass import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.boot.test.IntegrationTest -import org.springframework.boot.test.WebIntegrationTest import org.springframework.boot.test.context.SpringBootContextLoader +import org.springframework.boot.test.context.SpringBootTest import org.springframework.cloud.client.discovery.EnableDiscoveryClient import org.springframework.cloud.client.loadbalancer.LoadBalanced import org.springframework.cloud.contract.stubrunner.StubFinder @@ -37,22 +36,19 @@ import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration import org.springframework.util.SocketUtils import org.springframework.web.client.RestTemplate - import spock.lang.Specification - /** * @author Marcin Grzejszczak */ @ContextConfiguration(classes = Config, loader = SpringBootContextLoader) -@WebIntegrationTest(randomPort = true) -@IntegrationTest("stubrunner.camel.enabled=false") +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = ["stubrunner.camel.enabled=false"]) @AutoConfigureStubRunner @DirtiesContext class StubRunnerSpringCloudAutoConfigurationSpec extends Specification { @Autowired StubFinder stubFinder @Autowired @LoadBalanced RestTemplate restTemplate - // TODO: this shouldn't be needed? @Autowired ZookeeperServiceDiscovery zookeeperServiceDiscovery @Autowired ConfigurableApplicationContext applicationContext diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationWithoutDiscoverySpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationWithoutDiscoverySpec.groovy new file mode 100644 index 0000000000..d20c0e153e --- /dev/null +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerSpringCloudAutoConfigurationWithoutDiscoverySpec.groovy @@ -0,0 +1,80 @@ +/* + * Copyright 2013-2016 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 + * + * http://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.cloud.contract.stubrunner.spring.cloud + +import org.junit.AfterClass +import org.junit.BeforeClass +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.test.context.SpringBootContextLoader +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.cloud.client.discovery.EnableDiscoveryClient +import org.springframework.cloud.client.loadbalancer.LoadBalanced +import org.springframework.cloud.contract.stubrunner.StubFinder +import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner +import org.springframework.cloud.zookeeper.discovery.RibbonZookeeperAutoConfiguration +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.test.annotation.DirtiesContext +import org.springframework.test.context.ContextConfiguration +import org.springframework.web.client.RestTemplate +import spock.lang.Specification +/** + * @author Marcin Grzejszczak + */ +@ContextConfiguration(classes = Config, loader = SpringBootContextLoader) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = ["stubrunner.camel.enabled=false", + "spring.cloud.zookeeper.enabled=false", + "spring.cloud.zookeeper.discovery.enabled=false"]) +@AutoConfigureStubRunner +@DirtiesContext +class StubRunnerSpringCloudAutoConfigurationWithoutDiscoverySpec extends Specification { + + @Autowired StubFinder stubFinder + @Autowired @LoadBalanced RestTemplate restTemplate + + @BeforeClass + @AfterClass + static void setupProps() { + System.clearProperty("stubrunner.stubs.repository.root"); + System.clearProperty("stubrunner.stubs.classifier"); + } + + // tag::test[] + def 'should make service discovery work'() { + expect: 'WireMocks are running' + "${stubFinder.findStubUrl('loanIssuance').toString()}/name".toURL().text == 'loanIssuance' + "${stubFinder.findStubUrl('fraudDetectionServer').toString()}/name".toURL().text == 'fraudDetectionServer' + and: 'Stubs can be reached via load service discovery' + restTemplate.getForObject('http://loanIssuance/name', String) == 'loanIssuance' + restTemplate.getForObject('http://someNameThatShouldMapFraudDetectionServer/name', String) == 'fraudDetectionServer' + } + // end::test[] + + @Configuration + @EnableAutoConfiguration(exclude = [RibbonZookeeperAutoConfiguration]) + @EnableDiscoveryClient + static class Config { + + @Bean + @LoadBalanced + RestTemplate restTemplate() { + return new RestTemplate() + } + } +}