Skip to content

Commit 56673bd

Browse files
Fails on no stubs for stubs Per Consumer
without this change the JAR gets downloaded, it contains mappings but there are no mappings that are actually matching the given consumer. Regardless, the WireMock server starts with no mappings with this change an exception is being thrown in that case fixes gh-2114
1 parent 03162b6 commit 56673bd

File tree

7 files changed

+114
-17
lines changed

7 files changed

+114
-17
lines changed

spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRepository.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.Collections;
3030
import java.util.List;
3131

32+
import io.micrometer.common.lang.Nullable;
3233
import org.apache.commons.logging.Log;
3334
import org.apache.commons.logging.LogFactory;
3435

@@ -57,7 +58,8 @@ class StubRepository {
5758

5859
private final StubRunnerOptions options;
5960

60-
StubRepository(File repository, List<HttpServerStub> httpServerStubs, StubRunnerOptions options) {
61+
StubRepository(File repository, List<HttpServerStub> httpServerStubs, StubRunnerOptions options,
62+
@Nullable StubConfiguration stubConfiguration) {
6163
if (!repository.isDirectory()) {
6264
throw new IllegalArgumentException("Missing descriptor repository under path [" + repository + "]");
6365
}
@@ -70,13 +72,18 @@ class StubRepository {
7072
this.options = options;
7173
this.stubs = stubs();
7274
this.contracts = contracts();
75+
if (options.isFailOnNoStubs() && this.stubs.isEmpty() && this.contracts.isEmpty()) {
76+
throw new IllegalStateException("No stubs or contracts were found for ["
77+
+ (stubConfiguration != null ? stubConfiguration.toColonSeparatedDependencyNotation() : null)
78+
+ "] and the switch to fail on no stubs was set.");
79+
}
7380
if (log.isTraceEnabled()) {
7481
log.trace("Found the following contracts " + this.contracts);
7582
}
7683
}
7784

7885
StubRepository(File repository) {
79-
this(repository, new ArrayList<>(), new StubRunnerOptionsBuilder().build());
86+
this(repository, new ArrayList<>(), new StubRunnerOptionsBuilder().build(), null);
8087
}
8188

8289
public File getPath() {

spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunner.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ public StubRunner(StubRunnerOptions stubRunnerOptions, String repositoryPath, St
6464
this.stubsConfiguration = stubsConfiguration;
6565
this.stubRunnerOptions = stubRunnerOptions;
6666
List<HttpServerStub> serverStubs = SpringFactoriesLoader.loadFactories(HttpServerStub.class, null);
67-
this.stubRepository = new StubRepository(new File(repositoryPath), serverStubs, this.stubRunnerOptions);
67+
this.stubRepository = new StubRepository(new File(repositoryPath), serverStubs, this.stubRunnerOptions,
68+
stubsConfiguration);
6869
AvailablePortScanner portScanner = new AvailablePortScanner(stubRunnerOptions.getMinPortValue(),
6970
stubRunnerOptions.getMaxPortValue());
7071
this.localStubRunner = new StubRunnerExecutor(portScanner, contractVerifierMessaging, serverStubs);

spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/StubRepositorySpec.groovy

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,26 @@ class StubRepositorySpec extends Specification {
2525
def 'should retrieve all descriptors for given project'() {
2626
given:
2727
StubRepository repository = new StubRepository(REPOSITORY_LOCATION,
28-
[], new StubRunnerOptionsBuilder().build())
28+
[], new StubRunnerOptionsBuilder().build(), null)
2929
int expectedDescriptorsSize = 8
3030
when:
3131
List<File> descriptors = repository.getStubs()
3232
then:
3333
descriptors.size() == expectedDescriptorsSize
3434
}
3535

36-
def 'should return empty list if files are missing'() {
37-
given:
38-
StubRepository repository = new StubRepository(new File('src/test/resources/emptyrepo'),
39-
[], new StubRunnerOptionsBuilder().build())
36+
def 'should throw an exception when no stubs or contracts are present'() {
4037
when:
41-
List<File> descriptors = repository.getStubs()
38+
new StubRepository(new File('src/test/resources/emptyrepo'),
39+
[], new StubRunnerOptionsBuilder().build(), null)
4240
then:
43-
descriptors.empty
41+
thrown(IllegalStateException)
4442
}
4543

4644
def 'should throw an exception if directory with mappings is missing'() {
4745
when:
4846
new StubRepository(new File('src/test/resources/nonexistingrepo'), [],
49-
new StubRunnerOptionsBuilder().build())
47+
new StubRunnerOptionsBuilder().build(), null)
5048
then:
5149
thrown(IllegalArgumentException)
5250
}
@@ -56,7 +54,7 @@ class StubRepositorySpec extends Specification {
5654
StubRepository repository = new StubRepository(REPOSITORY_LOCATION,
5755
[], new StubRunnerOptionsBuilder()
5856
.withStubPerConsumer(true)
59-
.withConsumerName("ping").build())
57+
.withConsumerName("ping").build(), null)
6058
int expectedDescriptorsSize = 1
6159
when:
6260
List<File> descriptors = repository.stubs

spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/StubRunnerExecutorSpec.groovy

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class StubRunnerExecutorSpec extends Specification {
4040
def setup() {
4141
portScanner = new AvailablePortScanner(MIN_PORT, MAX_PORT)
4242
repository = new StubRepository(new File('src/test/resources/repository'),
43-
[], new StubRunnerOptionsBuilder().build())
43+
[], stubRunnerOptions, null)
4444
}
4545

4646
def 'should provide URL for given relative path of stub'() {
@@ -173,7 +173,7 @@ class StubRunnerExecutorSpec extends Specification {
173173
when:
174174
executor.runStubs(stubRunnerOptions,
175175
new StubRepository(new File('src/test/resources/repository/httpcontract'),
176-
[], new StubRunnerOptionsBuilder().build()), stubConf)
176+
[], new StubRunnerOptionsBuilder().build(), null), stubConf)
177177
then:
178178
!executor.trigger()
179179
!executor.trigger("missing", "label")
@@ -186,10 +186,11 @@ class StubRunnerExecutorSpec extends Specification {
186186
given:
187187
def stubConf = new StubConfiguration('asd', 'asd', 'asd', '')
188188
StubRunnerExecutor executor = new StubRunnerExecutor(portScanner)
189+
stubRunnerOptions = new StubRunnerOptionsBuilder().withFailOnNoStubs(false).build()
189190
when:
190191
RunningStubs stubs = executor.runStubs(stubRunnerOptions,
191192
new StubRepository(new File('src/test/resources/emptyrepo'),
192-
[], new StubRunnerOptionsBuilder().build()), stubConf)
193+
[], stubRunnerOptions, null), stubConf)
193194
then:
194195
stubs.getPort('asd') == -1
195196
cleanup:
@@ -204,7 +205,7 @@ class StubRunnerExecutorSpec extends Specification {
204205
def stubConf = new StubConfiguration('asd', 'asd', 'asd', '')
205206
executor.runStubs(stubRunnerOptions,
206207
new StubRepository(new File('src/test/resources/messages'),
207-
[], new StubRunnerOptionsBuilder().build()), stubConf)
208+
[], new StubRunnerOptionsBuilder().build(), null), stubConf)
208209
boolean triggered = executor.trigger("trigger")
209210
then:
210211
triggered

spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/StubRunnerFactorySpec.groovy

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ import org.springframework.cloud.contract.verifier.messaging.noop.NoOpStubMessag
2424

2525
class StubRunnerFactorySpec extends Specification {
2626

27+
static final String MAPPING = '''
28+
{
29+
"request": {
30+
"method": "GET",
31+
"url": "/hello"
32+
},
33+
"response": {
34+
"status": 200,
35+
"body": "Hello world!",
36+
"headers": {
37+
"Content-Type": "text/plain"
38+
}
39+
}
40+
}
41+
'''
42+
2743
@Rule
2844
TemporaryFolder folder = new TemporaryFolder()
2945

@@ -42,6 +58,7 @@ class StubRunnerFactorySpec extends Specification {
4258
def "Should download stub definitions many times"() {
4359
given:
4460
folder.newFolder("mappings")
61+
folder.newFile("hello.json").text = MAPPING
4562
1 * downloader.downloadAndUnpackStubJar(_) >> new AbstractMap.SimpleEntry(new StubConfiguration('a:b'), folder.root)
4663
1 * downloader.downloadAndUnpackStubJar(_) >> new AbstractMap.SimpleEntry(new StubConfiguration('c:d'), folder.root)
4764
when:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2013-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.contract.stubrunner.spring.cloud
18+
19+
import java.util.function.Function
20+
21+
import org.junit.jupiter.api.Test
22+
23+
import org.springframework.boot.autoconfigure.AutoConfigurations
24+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
25+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration
26+
import org.springframework.boot.test.context.runner.ApplicationContextRunner
27+
import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner
28+
import org.springframework.cloud.contract.stubrunner.spring.StubRunnerConfiguration
29+
import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties
30+
import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration
31+
import org.springframework.cloud.zookeeper.ZookeeperAutoConfiguration
32+
import org.springframework.context.annotation.Bean
33+
import org.springframework.context.annotation.Configuration
34+
import org.springframework.context.annotation.Import
35+
import org.springframework.test.context.ActiveProfiles
36+
37+
import static org.assertj.core.api.Assertions.assertThat
38+
39+
@AutoConfigureStubRunner(ids = "org.springframework.cloud.contract.verifier.stubs:producerWithMultipleConsumers",
40+
repositoryRoot = "classpath:m2repo/repository/",
41+
stubsMode = StubRunnerProperties.StubsMode.REMOTE,
42+
stubsPerConsumer = true)
43+
@ActiveProfiles("streamconsumer")
44+
class StubRunnerStubsPerConsumerNotMatchingConsumerSpec {
45+
46+
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
47+
.withConfiguration(AutoConfigurations.of(Config))
48+
.withPropertyValues("spring.application.name=bar-not-matching-consumer",
49+
"stubrunner.jms.enabled=false", "spring.profiles.active=streamconsumer", "spring.cloud.discovery.enabled=false", "spring.cloud.service-registry.auto-registration.enabled=false", "stubrunner.ids=org.springframework.cloud.contract.verifier.stubs:producerWithMultipleConsumers", "stubrunner.repositoryRoot=classpath:m2repo/repository/", "stubrunner.stubsMode=REMOTE", "stubrunner.stubsPerConsumer=true");
50+
51+
@Test
52+
void 'should fail to start when JAR is found but there are no stubs or contracts'() {
53+
expect:
54+
this.contextRunner.run((context) -> {
55+
assertThat(context).hasFailed();
56+
assertThat(context.getStartupFailure()).hasMessageContaining("No stubs or contracts were found for [org.springframework.cloud.contract.verifier.stubs:producerWithMultipleConsumers:0.0.1-SNAPSHOT:stubs] and the switch to fail on no stubs was set")
57+
});
58+
}
59+
60+
@Configuration
61+
@EnableAutoConfiguration(exclude = [ZookeeperAutoConfiguration])
62+
@ImportAutoConfiguration(TestChannelBinderConfiguration.class)
63+
@Import(value = StubRunnerConfiguration)
64+
static class Config {
65+
@Bean
66+
Function output() {
67+
return { Object o ->
68+
println(o)
69+
return o
70+
}
71+
}
72+
}
73+
}

spring-cloud-contract-stub-runner/src/test/java/org/springframework/cloud/contract/stubrunner/StubRepositoryTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class StubRepositoryTest {
3636
public void should_prefer_custom_yaml_converter_over_standard() {
3737
// given:
3838
StubRepository repository = new StubRepository(YAML_REPOSITORY_LOCATION, new ArrayList<>(),
39-
new StubRunnerOptionsBuilder().build());
39+
new StubRunnerOptionsBuilder().build(), null);
4040
int expectedDescriptorsSize = 1;
4141

4242
// when:

0 commit comments

Comments
 (0)