Stubbing service discovery out completely

without this change if you have a DiscoveryClient bean it's used for delegation. For tests with Stub Runner actually we don't want to delegate. There is an option however to turn on this delegation

fixes #82
This commit is contained in:
Marcin Grzejszczak
2016-09-23 10:40:57 +02:00
parent 01f4ad76be
commit 788b35aedb
4 changed files with 200 additions and 12 deletions

View File

@@ -1276,7 +1276,114 @@ Example of a `pom.xml` inside the `server` folder.
[source,xml,indent=0]
----
Unresolved directive in verifier/introduction.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/samples/standalone/contracts/com/example/server/pom.xml[indent=0]
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Server Stubs</name>
<description>POM used to install locally stubs for consumer side</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.BUILD-SNAPSHOT</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<spring-cloud-contract.version>1.0.0.BUILD-SNAPSHOT</spring-cloud-contract.version>
<spring-cloud-dependencies.version>Camden.BUILD-SNAPSHOT</spring-cloud-dependencies.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<!-- By default it would search under src/test/resources/ -->
<contractsDirectory>${project.basedir}</contractsDirectory>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
----
As you can see there are no dependencies other than the Spring Cloud Contract Verifier Maven plugin.
Those poms are necessary for the consumer side to run `mvn clean install -DskipTests` to locally install
@@ -1286,13 +1393,77 @@ The `pom.xml` in the root folder can look like this:
[source,xml,indent=0]
----
Unresolved directive in verifier/introduction.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/samples/standalone/contracts/pom.xml[indent=0]
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.standalone</groupId>
<artifactId>contracts</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Spring Cloud Contract Verifier Http Server Sample</name>
<description>Spring Cloud Contract Verifier Http Server Sample</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>contracts</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<attach>true</attach>
<descriptor>${basedir}/src/assembly/contracts.xml</descriptor>
<!-- If you want an explicit classifier remove the following line -->
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
----
It's using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here:
[source,xml,indent=0]
----
Unresolved directive in verifier/introduction.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/samples/standalone/contracts/src/assembly/contracts.xml[indent=0]
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>project</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}</directory>
<outputDirectory>/</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
<excludes>
<exclude>**/${project.build.directory}/**</exclude>
<exclude>mvnw</exclude>
<exclude>mvnw.cmd</exclude>
<exclude>.mvn/**</exclude>
<exclude>src/**</exclude>
</excludes>
</fileSet>
</fileSets>
</assembly>
----
*Workflow*
@@ -1315,7 +1486,17 @@ of the JAR containing the contracts:
[source,xml,indent=0]
----
Unresolved directive in verifier/introduction.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom-with-repo.xml[tags=remote_config,indent=0]
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<configuration>
<contractsRepositoryUrl>http://link/to/your/nexus/or/artifactory/or/sth</contractsRepositoryUrl>
<contractDependency>
<groupId>com.example.standalone</groupId>
<artifactId>contracts</artifactId>
</contractDependency>
</configuration>
</plugin>
----
With this setup the JAR with groupid `com.example.standalone` and artifactid `contracts` will be downloaded

View File

@@ -195,6 +195,11 @@ You can match the artifactId of the stub with the name of your app by using the
You can disable Stub Runner Ribbon support by providing: `stubrunner.cloud.ribbon.enabled` equal to `false`
You can disable Stub Runner support by providing: `stubrunner.cloud.enabled` equal to `false`
TIP: By default all service discovery will be stubbed. That means that regardless of the fact if you have
an existing `DiscoveryClient` its results will be ignored. However, if you want to reuse it, just set
`stubrunner.cloud.delegate.enabled` to `true` and then your existing `DiscoveryClient` results will be
merged with the stubbed ones.
=== Stub Runner Boot Application
Spring Cloud Contract Verifier Stub Runner Boot is a Spring Boot application that exposes REST endpoints to

View File

@@ -115,7 +115,7 @@ class StubRunnerDiscoveryClient implements DiscoveryClient {
private List<ServiceInstance> getInstancesFromDelegate(String serviceId) {
try {
return this.delegate.getInstances(serviceId);
return new ArrayList<>(this.delegate.getInstances(serviceId));
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("Failed to fetch instances from delegate", e);
@@ -134,15 +134,17 @@ class StubRunnerDiscoveryClient implements DiscoveryClient {
@Override
public List<String> getServices() {
List<String> list = new ArrayList<>();
List<String> services = getServicesFromDelegate();
RunningStubs runningStubs = this.stubFinder.findAllRunningStubs();
services.addAll(runningStubs.getAllServicesNames());
return services;
list.addAll(services);
list.addAll(runningStubs.getAllServicesNames());
return list;
}
private List<String> getServicesFromDelegate() {
try {
return this.delegate.getServices();
return new ArrayList<>(this.delegate.getServices());
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("Failed to fetch services from delegate", e);

View File

@@ -19,7 +19,6 @@ 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;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.DiscoveryClient;
@@ -41,9 +40,10 @@ import org.springframework.context.annotation.Primary;
public class StubRunnerSpringCloudAutoConfiguration {
@Bean
@ConditionalOnBean(DiscoveryClient.class)
@Primary
@ConditionalOnBean(DiscoveryClient.class)
@ConditionalOnStubbedDiscoveryEnabled
@ConditionalOnProperty(value = "stubrunner.cloud.delegate.enabled", havingValue = "true")
public DiscoveryClient stubRunnerDiscoveryClientWrapper(DiscoveryClient discoveryClient,
StubFinder stubFinder,
StubMapperProperties stubMapperProperties,
@@ -53,9 +53,9 @@ public class StubRunnerSpringCloudAutoConfiguration {
@Bean
@Primary
@ConditionalOnMissingBean(DiscoveryClient.class)
@ConditionalOnStubbedDiscoveryEnabled
public DiscoveryClient stubRunnerDiscoveryClient(StubFinder stubFinder,
@ConditionalOnProperty(value = "stubrunner.cloud.delegate.enabled", havingValue = "false", matchIfMissing = true)
public DiscoveryClient noOpStubRunnerDiscoveryClient(StubFinder stubFinder,
StubMapperProperties stubMapperProperties,
@Value("${spring.application.name:unknown}") String springAppName) {
return new StubRunnerDiscoveryClient(stubFinder, stubMapperProperties, springAppName);