Merge branch '1.2.x' into 2.0.x
This commit is contained in:
@@ -20,6 +20,7 @@ import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
import org.apache.commons.logging.Log
|
||||
import org.apache.commons.logging.LogFactory
|
||||
@@ -39,14 +40,16 @@ import static org.springframework.cloud.contract.verifier.util.NamesUtil.beforeL
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.convertIllegalPackageChars
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.directoryToPackage
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.toLastDot
|
||||
|
||||
/**
|
||||
* @author Jakub Kubrynski, codearte.io
|
||||
*/
|
||||
@CompileStatic
|
||||
class TestGenerator {
|
||||
|
||||
private static final Log log = LogFactory.getLog(TestGenerator)
|
||||
private static final String DEFAULT_CLASS_PREFIX = "ContractVerifier"
|
||||
private static final String DEFAULT_TEST_PACKAGE = "org.springframework.cloud.contract.verifier.tests"
|
||||
private static final Log log = LogFactory.getLog(TestGenerator)
|
||||
|
||||
private final ContractVerifierConfigProperties configProperties
|
||||
private AtomicInteger counter = new AtomicInteger()
|
||||
@@ -104,7 +107,7 @@ class TestGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private String relativizeContractPath(Map.Entry<Path, Collection<Path>> entry) {
|
||||
private String relativizeContractPath(Map.Entry<Path, Collection<ContractMetadata>> entry) {
|
||||
Path relativePath = configProperties.contractsDslDir.toPath().relativize(entry.getKey())
|
||||
if (StringUtils.isEmpty(relativePath.toString())) {
|
||||
return DEFAULT_CLASS_PREFIX
|
||||
@@ -115,7 +118,7 @@ class TestGenerator {
|
||||
private void processIncludedDirectory(
|
||||
final String includedDirectoryRelativePath, Collection<ContractMetadata> contracts, final String basePackageNameForClass) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Collected contracts with metadata ${contracts}")
|
||||
log.debug("Collected contracts with metadata ${contracts} relative path is [${includedDirectoryRelativePath}]")
|
||||
}
|
||||
if (contracts.size()) {
|
||||
def className = afterLast(includedDirectoryRelativePath.toString(), File.separator) + resolveNameSuffix()
|
||||
|
||||
@@ -18,6 +18,9 @@ package org.springframework.cloud.contract.verifier.builder
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
import org.apache.commons.logging.Log
|
||||
import org.apache.commons.logging.LogFactory
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework
|
||||
import org.springframework.cloud.contract.verifier.util.NamesUtil
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
@@ -33,6 +36,8 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig
|
||||
@PackageScope
|
||||
class ClassBuilder {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ClassBuilder)
|
||||
|
||||
private static final String SEPARATOR = "_REPLACEME_"
|
||||
|
||||
private final String className
|
||||
@@ -72,11 +77,15 @@ class ClassBuilder {
|
||||
}
|
||||
|
||||
protected static String retrieveBaseClass(ContractVerifierConfigProperties properties, String includedDirectoryRelativePath) {
|
||||
String contractPathAsPackage = includedDirectoryRelativePath.replace(File.separator, ".")
|
||||
String contractPackage = includedDirectoryRelativePath.replace(File.separator, SEPARATOR)
|
||||
// package mapping takes super precedence
|
||||
if (properties.baseClassMappings) {
|
||||
Map.Entry<String, String> mapping = properties.baseClassMappings.find { String pattern, String fqn ->
|
||||
return contractPackage.matches(pattern)
|
||||
return contractPathAsPackage.matches(pattern)
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Matching pattern for contract package [${contractPathAsPackage}] with setup ${properties.baseClassMappings} is [${mapping}]")
|
||||
}
|
||||
if (mapping) {
|
||||
return mapping.value
|
||||
|
||||
@@ -40,7 +40,11 @@ class HandlebarsJsonPathHelper implements Helper<Map<String, Object>> {
|
||||
private Object returnObjectForTest(Object model, String jsonPath) {
|
||||
String body = removeSurroundingQuotes(((TestSideRequestTemplateModel) model).rawBody).replace('\\"', '"')
|
||||
DocumentContext documentContext = JsonPath.parse(body)
|
||||
return documentContext.read(jsonPath)
|
||||
Object value = documentContext.read(jsonPath)
|
||||
if (value instanceof Long) {
|
||||
return String.valueOf(value) + "L"
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
private String removeSurroundingQuotes(String body) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.contract.verifier.messaging.stream;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -28,6 +29,7 @@ import org.springframework.cloud.stream.test.binder.MessageCollector;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
@@ -54,7 +56,7 @@ public class StreamStubMessages implements MessageVerifier<Message<?>> {
|
||||
public void send(Message<?> message, String destination) {
|
||||
try {
|
||||
MessageChannel messageChannel = this.context
|
||||
.getBean(resolvedDestination(destination), MessageChannel.class);
|
||||
.getBean(resolvedDestination(destination, DefaultChannels.OUTPUT), MessageChannel.class);
|
||||
messageChannel.send(message);
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -68,7 +70,7 @@ public class StreamStubMessages implements MessageVerifier<Message<?>> {
|
||||
public Message<?> receive(String destination, long timeout, TimeUnit timeUnit) {
|
||||
try {
|
||||
MessageChannel messageChannel = this.context
|
||||
.getBean(resolvedDestination(destination), MessageChannel.class);
|
||||
.getBean(resolvedDestination(destination, DefaultChannels.INPUT), MessageChannel.class);
|
||||
return this.messageCollector.forChannel(messageChannel).poll(timeout, timeUnit);
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -78,10 +80,11 @@ public class StreamStubMessages implements MessageVerifier<Message<?>> {
|
||||
}
|
||||
}
|
||||
|
||||
private String resolvedDestination(String destination) {
|
||||
private String resolvedDestination(String destination, DefaultChannels defaultChannel) {
|
||||
try {
|
||||
BindingServiceProperties channelBindingServiceProperties = this.context
|
||||
.getBean(BindingServiceProperties.class);
|
||||
Map<String, String> channels = new HashMap<>();
|
||||
for (Map.Entry<String, BindingProperties> entry : channelBindingServiceProperties
|
||||
.getBindings().entrySet()) {
|
||||
if (destination.equals(entry.getValue().getDestination())) {
|
||||
@@ -89,9 +92,24 @@ public class StreamStubMessages implements MessageVerifier<Message<?>> {
|
||||
log.debug("Found a channel named [{}] with destination [{}]",
|
||||
entry.getKey(), destination);
|
||||
}
|
||||
return entry.getKey();
|
||||
channels.put(entry.getKey().toLowerCase(), destination);
|
||||
}
|
||||
}
|
||||
if (channels.size() == 1) {
|
||||
return channels.keySet().iterator().next();
|
||||
} else if (channels.size() > 0) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Found following channels [{}] for destination [{}]. "
|
||||
+ "Will pick the one that matches the default channel name or the first one if none is matching",
|
||||
channels, destination);
|
||||
}
|
||||
String defaultChannelName = channels.get(defaultChannel.name().toLowerCase());
|
||||
String matchingChannelName = StringUtils.hasText(defaultChannelName) ? defaultChannel.name().toLowerCase() : channels.keySet().iterator().next();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Picked channel name is [{}]", matchingChannelName);
|
||||
}
|
||||
return matchingChannelName;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Exception took place while trying to resolve the destination. Will assume the name [" + destination + "]", e);
|
||||
}
|
||||
@@ -109,3 +127,8 @@ public class StreamStubMessages implements MessageVerifier<Message<?>> {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
enum DefaultChannels {
|
||||
INPUT, OUTPUT
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.springframework.cloud.contract.verifier.builder
|
||||
|
||||
import spock.lang.Issue
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import spock.lang.Specification
|
||||
|
||||
@@ -49,6 +51,16 @@ class ClassBuilderSpec extends Specification {
|
||||
ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperClass'
|
||||
}
|
||||
|
||||
@Issue("701")
|
||||
def "should match base class when mapping regex has multiple folders"() {
|
||||
given:
|
||||
ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(
|
||||
baseClassMappings: ['.*bar.baz.some.*' : 'com.example.base.SuperClass'])
|
||||
String contractRelativeFolder = 'foo/bar/baz/some/package'.split("/").join(File.separator)
|
||||
expect:
|
||||
ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperClass'
|
||||
}
|
||||
|
||||
def "should return the first matching base class when provided mapping doesn't match"() {
|
||||
given:
|
||||
ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(
|
||||
|
||||
@@ -491,6 +491,58 @@ DocumentContext parsedJson = JsonPath.parse(json);
|
||||
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) }
|
||||
}
|
||||
|
||||
@Issue("#702")
|
||||
def "should generate proper type for large numbers [#methodBuilderName]"() {
|
||||
given:
|
||||
Contract contractDsl = Contract.make {
|
||||
request {
|
||||
method 'PUT'
|
||||
urlPath '/example/create'
|
||||
headers {
|
||||
contentType applicationJson()
|
||||
}
|
||||
body(
|
||||
[
|
||||
"name" : $(consumer(~/.+/), producer("string-1")),
|
||||
"updatedTs" : $(consumer(~/\d{13}/), producer(1531916906000L)),
|
||||
"isDisabled": $(consumer(regex(anyBoolean())), producer(true))
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
response {
|
||||
status 200
|
||||
headers {
|
||||
contentType applicationJsonUtf8()
|
||||
}
|
||||
body(
|
||||
[
|
||||
"id" : $(consumer(2222L), producer(~/\d+/)),
|
||||
"name" : fromRequest().body("name"),
|
||||
"updatedTs" : fromRequest().body("updatedTs"),
|
||||
"isDisabled": fromRequest().body("isDisabled")
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
MethodBodyBuilder builder = methodBuilder(contractDsl)
|
||||
BlockBuilder blockBuilder = new BlockBuilder(" ")
|
||||
when:
|
||||
builder.appendTo(blockBuilder)
|
||||
then:
|
||||
String test = blockBuilder.toString()
|
||||
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test)
|
||||
test.contains('''assertThatJson(parsedJson).field("['updatedTs']").isEqualTo(1531916906000L)''')
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(contractDsl)
|
||||
where:
|
||||
methodBuilderName | methodBuilder
|
||||
"MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) }
|
||||
"MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) }
|
||||
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) }
|
||||
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) }
|
||||
}
|
||||
|
||||
@Issue("#465")
|
||||
def "should work for '/' url for [#methodBuilderName]"() {
|
||||
given:
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package org.springframework.cloud.contract.verifier.messaging.stream
|
||||
|
||||
import spock.lang.Issue
|
||||
import spock.lang.Specification
|
||||
|
||||
import org.springframework.cloud.stream.config.BindingProperties
|
||||
import org.springframework.cloud.stream.config.BindingServiceProperties
|
||||
import org.springframework.cloud.stream.test.binder.MessageCollector
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.messaging.MessageChannel
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
class StreamStubMessagesSpec extends Specification {
|
||||
|
||||
@Issue("694")
|
||||
def "should resolve input channel if input and output have same destination and receive is called"() {
|
||||
given:
|
||||
ApplicationContext applicationContext = Mock(ApplicationContext)
|
||||
BindingServiceProperties properties = new BindingServiceProperties(
|
||||
bindings: [
|
||||
input: new BindingProperties(destination: "verifications"),
|
||||
output: new BindingProperties(destination: "verifications"),
|
||||
]
|
||||
)
|
||||
MessageCollector collector = Stub(MessageCollector)
|
||||
and:
|
||||
applicationContext.getBean(BindingServiceProperties) >> properties
|
||||
applicationContext.getBean(MessageCollector) >> collector
|
||||
and:
|
||||
StreamStubMessages messages = new StreamStubMessages(applicationContext)
|
||||
when:
|
||||
messages.receive("verifications")
|
||||
then:
|
||||
1 * applicationContext.getBean("input", MessageChannel) >> null
|
||||
}
|
||||
|
||||
@Issue("694")
|
||||
def "should resolve output channel if input and output have same destination and send is called"() {
|
||||
given:
|
||||
ApplicationContext applicationContext = Mock(ApplicationContext)
|
||||
BindingServiceProperties properties = new BindingServiceProperties(
|
||||
bindings: [
|
||||
input: new BindingProperties(destination: "verifications"),
|
||||
output: new BindingProperties(destination: "verifications"),
|
||||
]
|
||||
)
|
||||
MessageCollector collector = Stub(MessageCollector)
|
||||
MessageChannel channel = Stub(MessageChannel)
|
||||
and:
|
||||
applicationContext.getBean(BindingServiceProperties) >> properties
|
||||
applicationContext.getBean(MessageCollector) >> collector
|
||||
and:
|
||||
StreamStubMessages messages = new StreamStubMessages(applicationContext)
|
||||
when:
|
||||
messages.send("foo", [:], "verifications")
|
||||
then:
|
||||
1 * applicationContext.getBean("output", MessageChannel) >> channel
|
||||
}
|
||||
|
||||
def "should resolve channel via destination for send and receive"() {
|
||||
given:
|
||||
ApplicationContext applicationContext = Mock(ApplicationContext)
|
||||
BindingServiceProperties properties = new BindingServiceProperties(
|
||||
bindings: [
|
||||
foo: new BindingProperties(destination: "verifications")
|
||||
]
|
||||
)
|
||||
MessageCollector collector = Stub(MessageCollector)
|
||||
MessageChannel channel = Stub(MessageChannel)
|
||||
and:
|
||||
applicationContext.getBean(BindingServiceProperties) >> properties
|
||||
applicationContext.getBean(MessageCollector) >> collector
|
||||
and:
|
||||
StreamStubMessages messages = new StreamStubMessages(applicationContext)
|
||||
when:
|
||||
messageInteraction(messages)
|
||||
then:
|
||||
1 * applicationContext.getBean("foo", MessageChannel) >> channel
|
||||
where:
|
||||
messageInteraction << [ { StreamStubMessages stream -> stream.send("foo", [:], "verifications")},
|
||||
{ StreamStubMessages stream -> stream.receive("verifications")}]
|
||||
}
|
||||
|
||||
def "should resolve channel via channel name for send and receive"() {
|
||||
given:
|
||||
ApplicationContext applicationContext = Mock(ApplicationContext)
|
||||
BindingServiceProperties properties = new BindingServiceProperties(
|
||||
bindings: [
|
||||
verifications: new BindingProperties(destination: "bar")
|
||||
]
|
||||
)
|
||||
MessageCollector collector = Stub(MessageCollector)
|
||||
MessageChannel channel = Stub(MessageChannel)
|
||||
and:
|
||||
applicationContext.getBean(BindingServiceProperties) >> properties
|
||||
applicationContext.getBean(MessageCollector) >> collector
|
||||
and:
|
||||
StreamStubMessages messages = new StreamStubMessages(applicationContext)
|
||||
when:
|
||||
messageInteraction(messages)
|
||||
then:
|
||||
1 * applicationContext.getBean("verifications", MessageChannel) >> channel
|
||||
where:
|
||||
messageInteraction << [ { StreamStubMessages stream -> stream.send("foo", [:], "verifications")},
|
||||
{ StreamStubMessages stream -> stream.receive("verifications")}]
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ import javax.inject.Inject
|
||||
@DirtiesContext
|
||||
@SpringBootTest(properties = "debug=true")
|
||||
@AutoConfigureMessageVerifier
|
||||
public class StreamMessagingApplicationSpec extends Specification {
|
||||
class StreamMessagingApplicationSpec extends Specification {
|
||||
|
||||
// ALL CASES
|
||||
@Inject MessageVerifier<Message<?>> contractVerifierMessaging
|
||||
|
||||
Reference in New Issue
Block a user