Rebranding (#287)
This commit is contained in:
committed by
GitHub
parent
a562775980
commit
817c232d3f
18
.travis.yml
18
.travis.yml
@@ -4,25 +4,9 @@ dist: trusty
|
||||
|
||||
before_install:
|
||||
- "export JAVA_OPTS='-Xmx1024m -XX:MaxPermSize=256m'"
|
||||
- "rm -rf $HOME/.m2/repository/io/codearte/accurest/stubs"
|
||||
- "mkdir $HOME/.m2/repository/io/codearte/accurest/ --parents"
|
||||
- "cp -r stub-runner/stub-runner-spring/src/test/resources/m2repo/repository/io/codearte/accurest/stubs $HOME/.m2/repository/io/codearte/accurest/"
|
||||
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
|
||||
install: ./gradlew assemble -s
|
||||
script: ./gradlew check funcTest install -s --continue && jdk_switcher use oraclejdk8 && ./scripts/runTests.sh && jdk_switcher use $TRAVIS_JDK_VERSION && ./gradlew uploadSnapshotArchives -x check -s
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# Automatic snapshot release only in Java 7 build
|
||||
- jdk: oraclejdk7
|
||||
env:
|
||||
- DO_RELEASE=true
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: NbEQ9t5nGKW0LKmOSV4rTiEbYJARM2rynQBdSXkoILbp+nNaCD6uN41tUu8HrjgbjUDMepFUU+hmGQ47Q2vz5L3NzvW+oHBLgrIu6uAimpdR8qyBE899MBKPE19LsvUOeE9B9TydJgYlY+UEYgxwssUwxsN0RqyY4EErQWMNC8k=
|
||||
- secure: zCjkMhjF5TbZehNmOK7EV68J35tuc0etWG/ia0eVTjgIv2kp9islJZ3+Jm/gDgkcv2Ydq3oAU2jFbVkUPSSstV3L5KANsighm2qn9tVzRrbTCfM55zcBhnoE0oZHTPNrLoScz0X5sM8Xuvi6ChjGf+lqAxnFW6tFMjx+1uhUIXU=
|
||||
|
||||
script: ./gradlew check funcTest install -s --continue && jdk_switcher use oraclejdk8 && ./scripts/runTests.sh
|
||||
|
||||
190
README.adoc
Normal file
190
README.adoc
Normal file
@@ -0,0 +1,190 @@
|
||||
// Do not edit this file (e.g. go instead to src/main/asciidoc)
|
||||
|
||||
:core_path: ../../../..
|
||||
:verifier_root_path: {core_path}/spring-cloud-contract-verifier
|
||||
:verifier_core_path: {verifier_root_path}/spring-cloud-contract-verifier-core
|
||||
:stubrunner_core_path: {core_path}/spring-cloud-contract-stub-runner
|
||||
:documentation_url: http://codearte.github.io/accurest
|
||||
|
||||
= Spring Cloud Contract Verifier
|
||||
|
||||
== Introduction
|
||||
|
||||
Just to make long story short - Spring Cloud Contract Verifier is a tool that enables Consumer Driven Contract (CDC) development of JVM-based applications. It is shipped
|
||||
with __Contract Definition Language__ (DSL). Contract definitions are used to produce following resources:
|
||||
|
||||
* JSON stub definitions to be used by Wiremock when doing integration testing on the client code (__client tests__).
|
||||
Test code must still be written by hand, test data is produced by Spring Cloud Contract Verifier.
|
||||
* Messaging routes if you're using one. We're integrating with Spring Integration, Spring Cloud Stream and Apache Camel. You can however set your own integrations if you want to
|
||||
* Acceptance tests (in JUnit or Spock) used to verify if server-side implementation of the API is compliant with the contract (__server tests__).
|
||||
Full test is generated by Spring Cloud Contract Verifier.
|
||||
|
||||
Spring Cloud Contract Verifier moves TDD to the level of software architecture.
|
||||
|
||||
=== Why?
|
||||
|
||||
Let us assume that we have a system comprising of multiple microservices:
|
||||
|
||||
image::Deps.png[Microservices Architecture]
|
||||
|
||||
==== Testing issues
|
||||
|
||||
If we wanted to test the application in top left corner if it can communicate with other services then we could do one of two things:
|
||||
|
||||
- deploy all microservices and perform end to end tests
|
||||
- mock other microservices in unit / integration tests
|
||||
|
||||
Both have their advantages but also a lot of disadvantages. Let's focus on the latter.
|
||||
|
||||
*Deploy all microservices and perform end to end tests*
|
||||
|
||||
Advantages:
|
||||
|
||||
- simulates production
|
||||
- tests real communication between services
|
||||
|
||||
Disadvantages:
|
||||
|
||||
- to test one microservice we would have to deploy 6 microservices, a couple of databases etc.
|
||||
- the environment where the tests would be conducted would be locked for a single suite of tests (i.e. nobody else would be able to run the tests in the meantime).
|
||||
- long to run
|
||||
- very late feedback
|
||||
- extremely hard to debug
|
||||
|
||||
*Mock other microservices in unit / integration tests*
|
||||
|
||||
Advantages:
|
||||
|
||||
- very fast feedback
|
||||
- no infrastructure requirements
|
||||
|
||||
Disadvantages:
|
||||
|
||||
- the implementor of the service creates stubs thus they might have nothing to do with the reality
|
||||
- you can go to production with passing tests and failing production
|
||||
|
||||
To solve the aforementioned issues Spring Cloud Contract Verifier with Stub Runner were created. Their main idea is to give you very fast feedback, without the need
|
||||
to set up the whole world of microservices.
|
||||
|
||||
image::Stubs1.png[Stubbed Services]
|
||||
|
||||
If you work on stubs then the only applications you need are those that your application is using directly.
|
||||
|
||||
image::Stubs2.png[Stubbed Services]
|
||||
|
||||
Spring Cloud Contract Verifier gives you the certainty that the stubs that you're using were created by the service that you're calling. Also if you can use them it means that they were
|
||||
tested against the producer's side. In other words - you can trust those stubs.
|
||||
|
||||
|
||||
=== Purposes
|
||||
|
||||
The main purposes of Spring Cloud Contract Verifier with Stub Runner are:
|
||||
|
||||
- to ensure that WireMock / Messaging stubs (used when developing the client) are doing exactly what actual server-side implementation will do,
|
||||
- to promote ATDD method and Microservices architectural style,
|
||||
- to provide a way to publish changes in contracts that are immediately visible on both sides,
|
||||
- to generate boilerplate test code used on the server side.
|
||||
|
||||
=== Client Side
|
||||
|
||||
During the tests you want to have a Wiremock instance / Messaging route up and running that simulates the service Y.
|
||||
You would like to feed that instance with a proper stub definition. That stub definition would need
|
||||
to be valid and should also be reusable on the server side.
|
||||
|
||||
__Summing it up:__ On this side, in the stub definition, you can use patterns for request stubbing and you need exact
|
||||
values for responses.
|
||||
|
||||
=== Server Side
|
||||
|
||||
Being a service Y since you are developing your stub, you need to be sure that it's actually resembling your
|
||||
concrete implementation. You can't have a situation where your stub acts in one way and your application on
|
||||
production behaves in a different way.
|
||||
|
||||
That's why from the provided stub acceptance tests will be generated that will ensure
|
||||
that your application behaves in the same way as you define in your stub.
|
||||
|
||||
__Summing it up:__ On this side, in the stub definition, you need exact values as request and can use patterns/methods
|
||||
for response verification.
|
||||
|
||||
=== Dependencies
|
||||
|
||||
Spring Cloud Contract Verifier and Stub Runner are using the following libraries
|
||||
|
||||
- http://wiremock.org/[WireMock]
|
||||
- https://github.com/jayway/JsonPath[Jayway JSONPath]
|
||||
- https://github.com/marcingrzejszczak/jsonassert[JSONAssert from Marcin Grzejszczak]
|
||||
|
||||
=== Additional links
|
||||
|
||||
Below you can find some resources related to Spring Cloud Contract Verifier and Stub Runner. Note that some can be outdated since the Spring Cloud Contract Verifier project
|
||||
is under constant development.
|
||||
|
||||
==== Videos
|
||||
|
||||
*Olga Maciaszek-Sharma talking about Accurest (Spring Cloud Contract Verifier predecessor)*
|
||||
|
||||
video::daafmTYFoDU[youtube]
|
||||
|
||||
*Marcin Grzejszczak and Jakub Kubryński talking about Accurest (Spring Cloud Contract Verifier predecessor)*
|
||||
|
||||
video::130779882[vimeo]
|
||||
|
||||
==== Readings
|
||||
|
||||
- http://www.slideshare.net/MarcinGrzejszczak/stick-to-the-rules-consumer-driven-contracts-201507-confitura[Slides from Marcin Grzejszczak's talk about Accurest]
|
||||
- http://toomuchcoding.com/blog/categories/accurest/[Accurest related articles from Marcin Grzejszczak's blog]
|
||||
|
||||
=== Samples
|
||||
|
||||
Here you can find some https://github.com/Codearte/accurest-samples[working samples]. Check the readme of each project for more information.
|
||||
|
||||
== Documentation
|
||||
|
||||
You can read more about Spring Cloud Contract Verifier by reading the {documentation_url}[docs]
|
||||
|
||||
== Contributing
|
||||
|
||||
Spring Cloud is released under the non-restrictive Apache 2.0 license,
|
||||
and follows a very standard Github development process, using Github
|
||||
tracker for issues and merging pull requests into master. If you want
|
||||
to contribute even something trivial please do not hesitate, but
|
||||
follow the guidelines below.
|
||||
|
||||
=== Sign the Contributor License Agreement
|
||||
Before we accept a non-trivial patch or pull request we will need you to sign the
|
||||
https://support.springsource.com/spring_committer_signup[contributor's agreement].
|
||||
Signing the contributor's agreement does not grant anyone commit rights to the main
|
||||
repository, but it does mean that we can accept your contributions, and you will get an
|
||||
author credit if we do. Active contributors might be asked to join the core team, and
|
||||
given the ability to merge pull requests.
|
||||
|
||||
=== Code of Conduct
|
||||
This project adheres to the Contributor Covenant https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc[code of
|
||||
conduct]. By participating, you are expected to uphold this code. Please report
|
||||
unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
=== Code Conventions and Housekeeping
|
||||
None of these is essential for a pull request, but they will all help. They can also be
|
||||
added after the original pull request but before a merge.
|
||||
|
||||
* Use the Spring Framework code format conventions. If you use Eclipse
|
||||
you can import formatter settings using the
|
||||
`eclipse-code-formatter.xml` file from the
|
||||
https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml[Spring
|
||||
Cloud Build] project. If using IntelliJ, you can use the
|
||||
http://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter
|
||||
Plugin] to import the same file.
|
||||
* Make sure all new `.java` files to have a simple Javadoc class comment with at least an
|
||||
`@author` tag identifying you, and preferably at least a paragraph on what the class is
|
||||
for.
|
||||
* Add the ASF license header comment to all new `.java` files (copy from existing files
|
||||
in the project)
|
||||
* Add yourself as an `@author` to the .java files that you modify substantially (more
|
||||
than cosmetic changes).
|
||||
* Add some Javadocs and, if you change the namespace, some XSD doc elements.
|
||||
* A few unit tests would help a lot as well -- someone has to do it.
|
||||
* If no-one else is using your branch, please rebase it against the current master (or
|
||||
other target branch in the main project).
|
||||
* When writing a commit message please follow http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions],
|
||||
if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit
|
||||
message (where XXXX is the issue number).
|
||||
47
README.md
47
README.md
@@ -1,47 +0,0 @@
|
||||
Accurest
|
||||
========
|
||||
|
||||
[](https://travis-ci.org/Codearte/accurest) [](https://maven-badges.herokuapp.com/maven-central/io.codearte.accurest/accurest-gradle-plugin)
|
||||
[](https://gitter.im/Codearte/accurest?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Consumer Driven Contracts verifier for Java
|
||||
|
||||
To make a long story short - Accurest is a tool for Consumer Driven Contract (CDC) development. Accurest ships an easy DSL for describing REST contracts for JVM-based applications.
|
||||
Since version 1.0.7 it also supports messaging.
|
||||
|
||||
The contract DSL is used by Accurest for two things:
|
||||
|
||||
1. generating WireMock's JSON stub definitions / stubbed messaging endpoints, allowing rapid development of the consumer side,
|
||||
generating JUnit / Spock's acceptance tests for the server - to verify if your API implementation is compliant with the contract.
|
||||
2. moving TDD to an architecture level.
|
||||
|
||||
For more information please go to the [Documentation](http://codearte.github.io/accurest/)
|
||||
|
||||
## Requirements
|
||||
|
||||
### Wiremock
|
||||
|
||||
In order to use Accurest with Wiremock you have to have __Wiremock in version at least 2.0.0-beta__ . Of course the higher the better :)
|
||||
|
||||
## Additional projects
|
||||
|
||||
### Stub Runner
|
||||
|
||||
Allows you to download WireMock stubs from the provided Maven repository and runs them in WireMock servers.
|
||||
|
||||
### Stub Runner JUnit
|
||||
|
||||
Stub Runner with JUnit rules
|
||||
|
||||
### Stub Runner Spring
|
||||
|
||||
Spring Configuration that automatically starts stubs upon Spring Context build up
|
||||
|
||||
### Stub Runner Spring Cloud
|
||||
|
||||
Spring Cloud AutoConfiguration that automatically starts stubs upon Spring Context build up and allows you to call the stubs
|
||||
as if they were registered in your service discovery
|
||||
|
||||
### [Accurest Maven Plugin](https://github.com/Codearte/accurest-maven-plugin)
|
||||
|
||||
Maven project support with standalone Accurest Stub Runner and Accurest Contracts to Wiremock mappings converter
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.codearte.accurest.wiremock
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import io.codearte.accurest.AccurestException
|
||||
|
||||
@CompileStatic
|
||||
class ConversionAccurestException extends AccurestException {
|
||||
|
||||
ConversionAccurestException(String message, Throwable cause) {
|
||||
super(message, cause)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package io.codearte.accurest.wiremock
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import io.codearte.accurest.dsl.WireMockStubStrategy
|
||||
import io.codearte.accurest.file.Contract
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
@CompileStatic
|
||||
class DslToWireMockClientConverter extends DslToWireMockConverter {
|
||||
|
||||
@Override
|
||||
String convertContent(String rootName, Contract contract) {
|
||||
String dslContent = contract.path.getText(StandardCharsets.UTF_8.toString())
|
||||
return new WireMockStubStrategy(rootName, contract, createGroovyDSLfromStringContent(dslContent)).toWireMockClientStub()
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package io.codearte.accurest.wiremock
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import io.codearte.accurest.dsl.GroovyDsl
|
||||
import io.codearte.accurest.util.AccurestDslConverter
|
||||
|
||||
@CompileStatic
|
||||
abstract class DslToWireMockConverter implements SingleFileConverter {
|
||||
|
||||
@Override
|
||||
boolean canHandleFileName(String fileName) {
|
||||
return fileName.endsWith('.groovy')
|
||||
}
|
||||
|
||||
@Override
|
||||
String generateOutputFileNameForInput(String inputFileName) {
|
||||
return inputFileName.replaceAll('.groovy', '.json')
|
||||
}
|
||||
|
||||
protected GroovyDsl createGroovyDSLfromStringContent(String groovyDslAsString) {
|
||||
return AccurestDslConverter.convert(groovyDslAsString)
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.codearte.accurest.wiremock
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import io.codearte.accurest.file.Contract
|
||||
|
||||
@CompileStatic
|
||||
interface SingleFileConverter {
|
||||
|
||||
boolean canHandleFileName(String fileName)
|
||||
|
||||
String convertContent(String rootName, Contract content)
|
||||
|
||||
String generateOutputFileNameForInput(String inputFileName)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method('POST')
|
||||
url '/login'
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method('GET')
|
||||
url '/cart'
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method('POST')
|
||||
url '/logout'
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method('PUT')
|
||||
headers {
|
||||
header 'Content-Type': 'application/json'
|
||||
}
|
||||
urlPattern $(client('/[0-9]{2}'), server('/12'))
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method('PUT')
|
||||
headers {
|
||||
header 'Content-Type': 'application/json'
|
||||
}
|
||||
urlPattern $(client('/[0-9]{2}'), server('/12'))
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method('PUT')
|
||||
headers {
|
||||
header 'Content-Type': 'application/json'
|
||||
}
|
||||
urlPattern $(client('/[0-9]{2}'), server('/12'))
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method('PUT')
|
||||
headers {
|
||||
header 'Content-Type': 'application/json'
|
||||
}
|
||||
urlPattern $(client('/[0-9]{2}'), server('/12'))
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package io.codearte.accurest
|
||||
|
||||
/**
|
||||
* @author Jakub Kubrynski
|
||||
*/
|
||||
class AccurestException extends RuntimeException {
|
||||
|
||||
AccurestException(String message) {
|
||||
super(message)
|
||||
}
|
||||
|
||||
AccurestException(String message, Throwable cause) {
|
||||
super(message, cause)
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package io.codearte.accurest.builder
|
||||
|
||||
import groovy.util.logging.Slf4j
|
||||
import io.codearte.accurest.config.AccurestConfigProperties
|
||||
import io.codearte.accurest.config.TestFramework
|
||||
import io.codearte.accurest.config.TestMode
|
||||
import io.codearte.accurest.dsl.GroovyDsl
|
||||
import io.codearte.accurest.file.Contract
|
||||
import io.codearte.accurest.util.NamesUtil
|
||||
/**
|
||||
* @author Jakub Kubrynski
|
||||
*/
|
||||
@Slf4j
|
||||
class MethodBuilder {
|
||||
|
||||
private final String methodName
|
||||
private final GroovyDsl stubContent
|
||||
private final AccurestConfigProperties configProperties
|
||||
private final boolean ignored
|
||||
|
||||
private MethodBuilder(String methodName, GroovyDsl stubContent, AccurestConfigProperties configProperties, boolean ignored) {
|
||||
this.ignored = ignored
|
||||
this.stubContent = stubContent
|
||||
this.methodName = methodName
|
||||
this.configProperties = configProperties
|
||||
}
|
||||
|
||||
static MethodBuilder createTestMethod(Contract contract, File stubsFile, GroovyDsl stubContent, AccurestConfigProperties configProperties) {
|
||||
log.debug("Stub content Groovy DSL [$stubContent]")
|
||||
String methodName = NamesUtil.camelCase(NamesUtil.toLastDot(NamesUtil.afterLast(stubsFile.path, File.separator)))
|
||||
return new MethodBuilder(methodName, stubContent, configProperties, contract.ignored)
|
||||
}
|
||||
|
||||
void appendTo(BlockBuilder blockBuilder) {
|
||||
if (configProperties.targetFramework == TestFramework.JUNIT) {
|
||||
blockBuilder.addLine('@Test')
|
||||
}
|
||||
if (ignored) {
|
||||
blockBuilder.addLine('@Ignore')
|
||||
}
|
||||
blockBuilder.addLine(configProperties.targetFramework.methodModifier + "validate_$methodName() throws Exception {")
|
||||
getMethodBodyBuilder().appendTo(blockBuilder)
|
||||
blockBuilder.addLine('}')
|
||||
}
|
||||
|
||||
private MethodBodyBuilder getMethodBodyBuilder() {
|
||||
if (stubContent.input || stubContent.outputMessage) {
|
||||
if (configProperties.targetFramework == TestFramework.JUNIT){
|
||||
return new JUnitMessagingMethodBodyBuilder(stubContent)
|
||||
}
|
||||
return new SpockMessagingMethodBodyBuilder(stubContent)
|
||||
}
|
||||
if (configProperties.testMode == TestMode.MOCKMVC && configProperties.targetFramework == TestFramework.JUNIT){
|
||||
return new MockMvcJUnitMethodBodyBuilder(stubContent)
|
||||
}
|
||||
if (configProperties.testMode == TestMode.JAXRSCLIENT) {
|
||||
if (configProperties.targetFramework == TestFramework.JUNIT){
|
||||
return new JaxRsClientJUnitMethodBodyBuilder(stubContent)
|
||||
}
|
||||
return new JaxRsClientSpockMethodRequestProcessingBodyBuilder(stubContent)
|
||||
}
|
||||
return new MockMvcSpockMethodRequestProcessingBodyBuilder(stubContent)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package io.codearte.accurest.builder
|
||||
|
||||
import io.codearte.accurest.dsl.GroovyDsl
|
||||
import io.codearte.accurest.dsl.internal.ExecutionProperty
|
||||
import io.codearte.accurest.dsl.internal.Header
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
/**
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2016-02-17
|
||||
*/
|
||||
class MockMvcJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
|
||||
MockMvcJUnitMethodBodyBuilder(GroovyDsl stubDefinition) {
|
||||
super(stubDefinition)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseCodeBlock(BlockBuilder bb) {
|
||||
bb.addLine("assertThat(response.statusCode()).isEqualTo($response.status.serverValue);")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseHeadersBlock(BlockBuilder bb) {
|
||||
response.headers?.collect { Header header ->\
|
||||
processHeaderElement(bb, header.name, header.serverValue)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
|
||||
blockBuilder.addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) {
|
||||
blockBuilder.addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
|
||||
blockBuilder.addLine("${exec.insertValue("response.header(\"$property\")")};")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package io.codearte.accurest.config
|
||||
|
||||
/**
|
||||
* @author Jakub Kubrynski
|
||||
*/
|
||||
enum TestMode {
|
||||
/**
|
||||
* Uses Spring's MockMvc
|
||||
*/
|
||||
MOCKMVC,
|
||||
|
||||
/**
|
||||
* Uses direct HTTP invocations
|
||||
*/
|
||||
EXPLICIT,
|
||||
|
||||
/**
|
||||
* Uses JAX-RS client
|
||||
*/
|
||||
JAXRSCLIENT
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package io.codearte.accurest.dsl
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.ToString
|
||||
import groovy.transform.TypeChecked
|
||||
/**
|
||||
* A better name for GroovyDsl
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@TypeChecked
|
||||
@EqualsAndHashCode
|
||||
@ToString(includeFields = true, includePackage = false, includeNames = true, includeSuper = true)
|
||||
class Accurest extends GroovyDsl {
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
package io.codearte.accurest.dsl
|
||||
|
||||
import groovy.json.JsonBuilder
|
||||
import groovy.transform.TypeChecked
|
||||
import io.codearte.accurest.dsl.internal.DslProperty
|
||||
import io.codearte.accurest.dsl.internal.Header
|
||||
import io.codearte.accurest.dsl.internal.Headers
|
||||
import io.codearte.accurest.util.ContentType
|
||||
import io.codearte.accurest.util.ContentUtils
|
||||
import io.codearte.accurest.util.MapConverter
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import static io.codearte.accurest.util.ContentUtils.extractValue
|
||||
import static io.codearte.accurest.util.MapConverter.transformValues
|
||||
|
||||
@TypeChecked
|
||||
abstract class BaseWireMockStubStrategy {
|
||||
|
||||
protected getStubSideValue(Object object) {
|
||||
return MapConverter.getStubSideValues(object)
|
||||
}
|
||||
|
||||
private static Closure transform = {
|
||||
it instanceof DslProperty ? transformValues(it.clientValue, transform) : it
|
||||
}
|
||||
|
||||
protected Map buildClientRequestHeadersSection(Headers headers) {
|
||||
if (!headers) {
|
||||
return null
|
||||
}
|
||||
return headers.entries.collectEntries { Header entry ->
|
||||
parseHeader(entry.name, entry.clientValue)
|
||||
}
|
||||
}
|
||||
|
||||
protected Map buildClientResponseHeadersSection(Headers headers) {
|
||||
if (!headers) {
|
||||
return null
|
||||
}
|
||||
return headers.entries.collectEntries { Header entry ->
|
||||
[(entry.name): entry.clientValue]
|
||||
}
|
||||
}
|
||||
|
||||
protected Map parseHeader(String entryKey, Object entry) {
|
||||
return [(entryKey): [equalTo: entry]]
|
||||
}
|
||||
|
||||
protected Map parseHeader(String entryKey, String entry) {
|
||||
return [(entryKey): [equalTo: entry]]
|
||||
}
|
||||
|
||||
protected Map parseHeader(String entryKey, Pattern entry) {
|
||||
return [(entryKey): [matches: entry.pattern()]]
|
||||
}
|
||||
|
||||
public String parseBody(Object value, ContentType contentType) {
|
||||
return parseBody(value.toString(), contentType)
|
||||
}
|
||||
|
||||
public Boolean parseBody(Boolean value, ContentType contentType) {
|
||||
return value
|
||||
}
|
||||
|
||||
public String parseBody(Map map, ContentType contentType) {
|
||||
def transformedMap = MapConverter.getStubSideValues(map)
|
||||
return parseBody(toJson(transformedMap), contentType)
|
||||
}
|
||||
|
||||
public String parseBody(List list, ContentType contentType) {
|
||||
List result = []
|
||||
list.each {
|
||||
if (it instanceof Map) {
|
||||
result += MapConverter.getStubSideValues(it)
|
||||
} else {
|
||||
result += parseBody(it, contentType)
|
||||
}
|
||||
}
|
||||
return parseBody(toJson(result), contentType)
|
||||
}
|
||||
|
||||
public String parseBody(GString value, ContentType contentType) {
|
||||
Object processedValue = extractValue(value, contentType, { DslProperty dslProperty -> dslProperty.clientValue })
|
||||
if (processedValue instanceof GString) {
|
||||
return parseBody(processedValue.toString(), contentType)
|
||||
}
|
||||
return parseBody(processedValue, contentType)
|
||||
}
|
||||
|
||||
public String parseBody(String value, ContentType contentType) {
|
||||
return value
|
||||
}
|
||||
|
||||
private static toJson(Object value) {
|
||||
return new JsonBuilder(value).toString()
|
||||
}
|
||||
|
||||
protected ContentType tryToGetContentType(Object body, Headers headers) {
|
||||
ContentType contentType = ContentUtils.recognizeContentTypeFromHeader(headers)
|
||||
if (contentType == ContentType.UNKNOWN) {
|
||||
if (!body) {
|
||||
return ContentType.UNKNOWN
|
||||
}
|
||||
return ContentUtils.getClientContentType(body)
|
||||
}
|
||||
return contentType
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package io.codearte.accurest.dsl
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.ToString
|
||||
import groovy.transform.TypeChecked
|
||||
import io.codearte.accurest.dsl.internal.Input
|
||||
import io.codearte.accurest.dsl.internal.OutputMessage
|
||||
import io.codearte.accurest.dsl.internal.Request
|
||||
import io.codearte.accurest.dsl.internal.Response
|
||||
|
||||
@TypeChecked
|
||||
@EqualsAndHashCode
|
||||
@ToString(includeFields = true, includePackage = false, includeNames = true)
|
||||
class GroovyDsl {
|
||||
|
||||
Integer priority
|
||||
Request request
|
||||
Response response
|
||||
String label
|
||||
String description
|
||||
Input input
|
||||
OutputMessage outputMessage
|
||||
|
||||
static GroovyDsl make(Closure closure) {
|
||||
GroovyDsl dsl = new GroovyDsl()
|
||||
closure.delegate = dsl
|
||||
closure()
|
||||
return dsl
|
||||
}
|
||||
|
||||
void priority(int priority) {
|
||||
this.priority = priority
|
||||
}
|
||||
|
||||
void label(String label) {
|
||||
this.label = label
|
||||
}
|
||||
|
||||
void description(String description) {
|
||||
this.description = description
|
||||
}
|
||||
|
||||
void request(@DelegatesTo(Request) Closure closure) {
|
||||
this.request = new Request()
|
||||
closure.delegate = request
|
||||
closure()
|
||||
}
|
||||
|
||||
void response(@DelegatesTo(Response) Closure closure) {
|
||||
this.response = new Response()
|
||||
closure.delegate = response
|
||||
closure()
|
||||
}
|
||||
|
||||
void input(@DelegatesTo(Input) Closure closure) {
|
||||
this.input = new Input()
|
||||
closure.delegate = input
|
||||
closure()
|
||||
}
|
||||
|
||||
void outputMessage(@DelegatesTo(OutputMessage) Closure closure) {
|
||||
this.outputMessage = new OutputMessage()
|
||||
closure.delegate = outputMessage
|
||||
closure()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
@CompileStatic
|
||||
class ClientDslProperty extends DslProperty {
|
||||
|
||||
ClientDslProperty(Object singleValue) {
|
||||
super(singleValue)
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.ToString
|
||||
|
||||
@CompileStatic
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
@ToString(includePackage = false, includeNames = true)
|
||||
class DslProperty<T> {
|
||||
|
||||
final T clientValue
|
||||
final T serverValue
|
||||
|
||||
DslProperty(T clientValue, T serverValue) {
|
||||
this.clientValue = clientValue
|
||||
this.serverValue = serverValue
|
||||
}
|
||||
|
||||
DslProperty(T singleValue) {
|
||||
this.clientValue = singleValue
|
||||
this.serverValue = singleValue
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
@CompileStatic
|
||||
class ExecutionProperty {
|
||||
|
||||
private static final String PLACEHOLDER_VALUE = '\\$it'
|
||||
|
||||
final String executionCommand
|
||||
|
||||
ExecutionProperty(String executionCommand) {
|
||||
this.executionCommand = executionCommand
|
||||
}
|
||||
|
||||
String insertValue(String valueToInsert) {
|
||||
return executionCommand.replaceAll(PLACEHOLDER_VALUE, valueToInsert)
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.ToString
|
||||
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
@ToString(includePackage = false, includeFields = true, ignoreNulls = true, includeNames = true)
|
||||
@CompileStatic
|
||||
class Header extends DslProperty {
|
||||
|
||||
String name
|
||||
|
||||
Header(String name, DslProperty dslProperty) {
|
||||
super(dslProperty.clientValue, dslProperty.serverValue)
|
||||
this.name = name
|
||||
}
|
||||
|
||||
Header(String name, Object value) {
|
||||
super(value)
|
||||
this.name = name
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
|
||||
enum JSONCompareMode {
|
||||
STRICT, LENIENT, NON_EXTENSIBLE, STRICT_ORDER
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
|
||||
import groovy.json.JsonOutput
|
||||
import groovy.transform.CompileStatic
|
||||
import io.codearte.accurest.util.MapConverter
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@CompileStatic
|
||||
class JsonStructureConverter {
|
||||
|
||||
public static final String TEMPORARY_PLACEHOLDER = '###PLACEHOLDER###'
|
||||
public static final Pattern TEMPORARY_PATTERN_HOLDER = Pattern.compile(TEMPORARY_PLACEHOLDER)
|
||||
|
||||
static Object convertJsonStructureToObjectUnderstandingStructure(Object parsedJson,
|
||||
Closure<Boolean> retrievePlaceholders,
|
||||
Closure<String> performAdditionalLogicOnSerializedJson,
|
||||
Closure convertSerializedJsonToSth) {
|
||||
LinkedList<Object> queue = new LinkedList<>()
|
||||
def transformedJson = MapConverter.transformValues(parsedJson, {
|
||||
if(retrievePlaceholders(it)) {
|
||||
queue.push(it)
|
||||
return TEMPORARY_PLACEHOLDER
|
||||
}
|
||||
return it
|
||||
})
|
||||
String jsonAsString = JsonOutput.toJson(transformedJson)
|
||||
String transformedJsonAsString = performAdditionalLogicOnSerializedJson(jsonAsString)
|
||||
return convertSerializedJsonToSth(queue, transformedJsonAsString)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.ToString
|
||||
|
||||
@ToString(includePackage = false, includeFields = true, includeNames = true)
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
@CompileStatic
|
||||
class NamedProperty {
|
||||
|
||||
private static final String NAME = 'name'
|
||||
private static final String CONTENT = 'content'
|
||||
DslProperty name
|
||||
DslProperty value
|
||||
|
||||
NamedProperty(DslProperty name, DslProperty value) {
|
||||
this.name = name
|
||||
this.value = value
|
||||
}
|
||||
|
||||
NamedProperty(Map<String, DslProperty> namedMap) {
|
||||
this(namedMap?.get(NAME), namedMap?.get(CONTENT))
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
|
||||
class OptionalProperty {
|
||||
final Object value
|
||||
|
||||
OptionalProperty(Object value) {
|
||||
this.value = value
|
||||
}
|
||||
|
||||
String optionalPattern() {
|
||||
return "($value)?"
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.ToString
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
@ToString(includePackage = false, includeFields = true, ignoreNulls = true, includeNames = true)
|
||||
@TypeChecked
|
||||
class QueryParameters {
|
||||
|
||||
List<QueryParameter> parameters = []
|
||||
|
||||
void parameter(Map<String, Object> singleParameter) {
|
||||
Map.Entry<String, Object> first = singleParameter.entrySet().first()
|
||||
parameters << new QueryParameter(first?.key, first?.value)
|
||||
}
|
||||
|
||||
void parameter(String parameterName, Object parameterValue) {
|
||||
parameters << new QueryParameter(parameterName, parameterValue)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.ToString
|
||||
|
||||
@CompileStatic
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
@ToString(includePackage = false)
|
||||
class ServerDslProperty extends DslProperty {
|
||||
|
||||
ServerDslProperty(Object singleValue) {
|
||||
super(singleValue)
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.ToString
|
||||
|
||||
import static io.codearte.accurest.util.ValidateUtils.validateServerValueIsAvailable
|
||||
|
||||
@ToString(includePackage = false, includeFields = true, includeNames = true)
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
@CompileStatic
|
||||
class Url extends DslProperty {
|
||||
|
||||
QueryParameters queryParameters
|
||||
|
||||
Url(DslProperty prop) {
|
||||
super(prop.clientValue, prop.serverValue)
|
||||
validateServerValueIsAvailable(prop.serverValue, "Url")
|
||||
}
|
||||
|
||||
Url(Object url) {
|
||||
super(url)
|
||||
validateServerValueIsAvailable(url, "Url")
|
||||
}
|
||||
|
||||
void queryParameters(@DelegatesTo(QueryParameters) Closure closure) {
|
||||
this.queryParameters = new QueryParameters()
|
||||
closure.delegate = queryParameters
|
||||
closure()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.ToString
|
||||
|
||||
@ToString(includePackage = false, includeFields = true, includeNames = true)
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
@CompileStatic
|
||||
class UrlPath extends Url {
|
||||
|
||||
UrlPath(String path) {
|
||||
super(path)
|
||||
}
|
||||
|
||||
UrlPath(DslProperty path) {
|
||||
super(path)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package io.codearte.accurest.file
|
||||
|
||||
import java.nio.file.Path
|
||||
|
||||
/**
|
||||
* @author Jakub Kubrynski
|
||||
*/
|
||||
class Contract {
|
||||
final Path path;
|
||||
final boolean ignored;
|
||||
final int groupSize
|
||||
final Integer order;
|
||||
|
||||
Contract(Path path, boolean ignored, int groupSize, Integer order) {
|
||||
this.groupSize = groupSize
|
||||
this.path = path
|
||||
this.ignored = ignored
|
||||
this.order = order
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Contract{" +
|
||||
"fileName=" + path.fileName +
|
||||
", ignored=" + ignored +
|
||||
", groupSize=" + groupSize +
|
||||
", order=" + order +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package io.codearte.accurest.util
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import io.codearte.accurest.dsl.GroovyDsl
|
||||
import org.codehaus.groovy.control.CompilerConfiguration
|
||||
|
||||
/**
|
||||
* Converts to Groovy DSL
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@CompileStatic
|
||||
class AccurestDslConverter {
|
||||
|
||||
static GroovyDsl convert(String dsl) {
|
||||
return groovyShell().evaluate(dsl) as GroovyDsl
|
||||
}
|
||||
|
||||
static GroovyDsl convert(File dsl) {
|
||||
return groovyShell().evaluate(dsl) as GroovyDsl
|
||||
}
|
||||
|
||||
private static GroovyShell groovyShell() {
|
||||
return new GroovyShell(AccurestDslConverter.classLoader, new Binding(), new CompilerConfiguration(sourceEncoding: 'UTF-8'))
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package io.codearte.accurest.util
|
||||
|
||||
enum ContentType {
|
||||
|
||||
JSON("application/json"),
|
||||
XML("application/xml"),
|
||||
UNKNOWN("application/octet-stream")
|
||||
|
||||
final String mimeType
|
||||
|
||||
ContentType(String mimeType) {
|
||||
this.mimeType = mimeType
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package io.codearte.accurest.util;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import com.toomuchcoding.jsonassert.JsonVerifiable;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
class FinishedDelegatingJsonVerifiable extends DelegatingJsonVerifiable {
|
||||
|
||||
FinishedDelegatingJsonVerifiable(JsonVerifiable delegate,
|
||||
LinkedList<String> methodsBuffer) {
|
||||
super(delegate, methodsBuffer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package io.codearte.accurest.util
|
||||
|
||||
class JsonPaths extends HashSet<MethodBufferingJsonVerifiable> {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package io.codearte.accurest.util;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public interface MethodBuffering {
|
||||
|
||||
String method();
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package io.codearte.accurest.util
|
||||
|
||||
/**
|
||||
* @author Jakub Kubrynski
|
||||
*/
|
||||
class NamesUtil {
|
||||
|
||||
static String beforeLast(String string, String separator) {
|
||||
if (string?.indexOf(separator) > -1) {
|
||||
return string.substring(0, string.lastIndexOf(separator))
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
static String afterLast(String string, String separator) {
|
||||
if (string?.indexOf(separator) > -1) {
|
||||
return string.substring(string.lastIndexOf(separator) + 1)
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
static String afterLastDot(String string) {
|
||||
return afterLast(string, '.')
|
||||
}
|
||||
|
||||
static String camelCase(String className) {
|
||||
if (!className) {
|
||||
return className
|
||||
}
|
||||
String firstChar = className.charAt(0).toLowerCase() as String
|
||||
return firstChar + className.substring(1)
|
||||
}
|
||||
|
||||
static String capitalize(String className) {
|
||||
if (!className) {
|
||||
return className
|
||||
}
|
||||
String firstChar = className.charAt(0).toUpperCase() as String
|
||||
return firstChar + className.substring(1)
|
||||
}
|
||||
|
||||
static String toLastDot(String string) {
|
||||
if (string?.indexOf('.') > -1) {
|
||||
return string.substring(0, string.lastIndexOf('.'))
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
static String packageToDirectory(String packageName) {
|
||||
return packageName.replace('.' as char, File.separatorChar)
|
||||
}
|
||||
|
||||
static String directoryToPackage(String directory) {
|
||||
return directory.replace(File.separator, '.')
|
||||
}
|
||||
|
||||
static String convertIllegalPackageChars(String packageName) {
|
||||
return packageName.replace('-', '_')
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
package io.codearte.accurest.util
|
||||
|
||||
import io.codearte.accurest.dsl.internal.DslProperty
|
||||
import org.codehaus.groovy.runtime.GStringImpl
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import static io.codearte.accurest.util.ContentUtils.extractValue
|
||||
import static org.apache.commons.lang3.StringEscapeUtils.escapeJson
|
||||
|
||||
public class RegexpBuilders {
|
||||
|
||||
public static String buildGStringRegexpForStubSide(GString gString) {
|
||||
new GStringImpl(
|
||||
gString.values.collect(this.&buildGStringRegexpForStubSide) as Object[],
|
||||
gString.strings.collect(this.&escapeSpecialRegexChars) as String[]
|
||||
)
|
||||
}
|
||||
|
||||
public static String buildGStringRegexpForStubSide(Pattern pattern) {
|
||||
return pattern.pattern()
|
||||
}
|
||||
|
||||
public static String buildGStringRegexpForStubSide(DslProperty dslProperty) {
|
||||
return buildGStringRegexpForStubSide(dslProperty.clientValue)
|
||||
}
|
||||
|
||||
public static String buildGStringRegexpForStubSide(Object o) {
|
||||
return escapeSpecialRegexChars(o.toString())
|
||||
}
|
||||
|
||||
public static String buildGStringRegexpForTestSide(GString gString) {
|
||||
new GStringImpl(
|
||||
gString.values.collect(this.&buildGStringRegexpForTestSide) as Object[],
|
||||
gString.strings.collect(this.&escapeSpecialRegexChars) as String[]
|
||||
)
|
||||
}
|
||||
|
||||
public static String buildGStringRegexpForTestSide(Pattern pattern) {
|
||||
return pattern.pattern()
|
||||
}
|
||||
|
||||
public static String buildGStringRegexpForTestSide(DslProperty dslProperty) {
|
||||
return buildGStringRegexpForTestSide(dslProperty.clientValue)
|
||||
}
|
||||
|
||||
public static String buildGStringRegexpForTestSide(Object o) {
|
||||
return o.toString().replaceAll('\\\\', '\\\\\\\\')
|
||||
}
|
||||
|
||||
private final static Pattern SPECIAL_REGEX_CHARS = Pattern.compile('[{}()\\[\\].+*?^$\\\\|]')
|
||||
|
||||
private static String escapeSpecialRegexChars(String str) {
|
||||
return SPECIAL_REGEX_CHARS.matcher(str).replaceAll('\\\\\\\\$0')
|
||||
}
|
||||
|
||||
private final static String WS = /\s*/
|
||||
|
||||
public static String buildJSONRegexpMatch(GString gString) {
|
||||
return buildJSONRegexpMatch(extractValue(gString, ContentType.JSON, { DslProperty dslProperty -> dslProperty.clientValue }))
|
||||
}
|
||||
|
||||
public static String buildJSONRegexpMatch(Map jsonMap) {
|
||||
return WS + "\\{" + jsonMap.collect(this.&buildJSONRegexpMatch).join(",") + "\\}" + WS
|
||||
}
|
||||
|
||||
public static String buildJSONRegexpMatch(List jsonList) {
|
||||
return WS + "\\[" + jsonList.collect(this.&buildJSONRegexpMatch).join(",") + "\\]" + WS
|
||||
}
|
||||
|
||||
public static String buildJSONRegexpMatch(Map.Entry<String, Object> entry) {
|
||||
return buildJSONRegexpMatchString(escapeJson(entry.key)) + ":" + buildJSONRegexpMatch(entry.value)
|
||||
}
|
||||
|
||||
public static String buildJSONRegexpMatch(Object value) {
|
||||
return buildJSONRegexpMatchStringOptionalQuotes(escapeJson(value.toString()))
|
||||
}
|
||||
|
||||
public static String buildJSONRegexpMatch(Pattern pattern) {
|
||||
return buildJSONRegexpMatchStringOptionalQuotes(pattern.pattern())
|
||||
}
|
||||
|
||||
public static String buildJSONRegexpMatchString(String value) {
|
||||
return WS + '"' + value + '"' + WS
|
||||
}
|
||||
|
||||
public static String buildJSONRegexpMatchStringOptionalQuotes(String value) {
|
||||
return WS + '"?' + value + '"?' + WS
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.codearte.accurest.util;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
class ShouldTraverse {
|
||||
final Object value;
|
||||
|
||||
ShouldTraverse(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package io.codearte.accurest.util
|
||||
|
||||
import groovy.transform.TypeChecked
|
||||
import io.codearte.accurest.dsl.internal.DslProperty
|
||||
import io.codearte.accurest.dsl.internal.MatchingStrategy
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import static io.codearte.accurest.dsl.internal.MatchingStrategy.Type.ABSENT
|
||||
import static io.codearte.accurest.dsl.internal.MatchingStrategy.Type.EQUAL_TO
|
||||
|
||||
@TypeChecked
|
||||
class ValidateUtils {
|
||||
|
||||
static Object validateServerValueIsAvailable(Object value) {
|
||||
validateServerValueIsAvailable(value, "Server value")
|
||||
return value
|
||||
}
|
||||
|
||||
static Object validateServerValueIsAvailable(Object value, String msg) {
|
||||
validateServerValue(value, msg)
|
||||
return value
|
||||
}
|
||||
|
||||
static void validateServerValue(Pattern pattern, String msg) {
|
||||
throw new IllegalStateException("$msg can't be a pattern for the server side")
|
||||
}
|
||||
|
||||
static List ALLOWED_MATCHING_TYPES_ON_SERVER_SIDE = [EQUAL_TO, ABSENT]
|
||||
|
||||
static void validateServerValue(MatchingStrategy matchingStrategy, String msg) {
|
||||
if (!ALLOWED_MATCHING_TYPES_ON_SERVER_SIDE.contains(matchingStrategy.type)) {
|
||||
throw new IllegalStateException("$msg can't be of a matching type: $matchingStrategy.type for the server side")
|
||||
}
|
||||
validateServerValue(matchingStrategy.serverValue, msg)
|
||||
}
|
||||
|
||||
static void validateServerValue(DslProperty value, String msg) {
|
||||
validateServerValue(value.serverValue, msg)
|
||||
}
|
||||
|
||||
static void validateServerValue(Object value, String msg) {
|
||||
// OK
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package io.codearte.accurest
|
||||
|
||||
import io.codearte.accurest.config.AccurestConfigProperties
|
||||
import io.codearte.accurest.config.TestFramework
|
||||
import spock.lang.Specification
|
||||
|
||||
class GeneratorScannerSpec extends Specification {
|
||||
|
||||
private SingleTestGenerator classGenerator = Mock(SingleTestGenerator)
|
||||
|
||||
def "should find all .json files and generate 6 classes for them"() {
|
||||
given:
|
||||
File resource = new File(this.getClass().getResource("/directory/with/stubs/stubsRepositoryIndicator").toURI())
|
||||
AccurestConfigProperties properties = new AccurestConfigProperties()
|
||||
properties.contractsDslDir = resource.parentFile
|
||||
TestGenerator testGenerator = new TestGenerator(properties, classGenerator, Stub(FileSaver))
|
||||
when:
|
||||
testGenerator.generateTestClasses("com.ofg")
|
||||
then:
|
||||
6 * classGenerator.buildClass(_, _, _) >> "qwerty"
|
||||
}
|
||||
|
||||
def "should create class with full package"() {
|
||||
given:
|
||||
AccurestConfigProperties properties = new AccurestConfigProperties(targetFramework: TestFramework.SPOCK)
|
||||
properties.contractsDslDir = new File(this.getClass().getResource("/directory/with/stubs/package").toURI())
|
||||
TestGenerator testGenerator = new TestGenerator(properties, classGenerator, Stub(FileSaver))
|
||||
when:
|
||||
testGenerator.generateTestClasses("com.ofg")
|
||||
then:
|
||||
1 * classGenerator.buildClass(_, 'exceptionsSpec', 'com.ofg') >> "spec"
|
||||
1 * classGenerator.buildClass(_, 'exceptionsSpec', 'com.ofg.v1') >> "spec1"
|
||||
1 * classGenerator.buildClass(_, 'exceptionsSpec', 'com.ofg.v2') >> "spec2"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package io.codearte.accurest
|
||||
|
||||
import io.codearte.accurest.config.AccurestConfigProperties
|
||||
import io.codearte.accurest.config.TestFramework
|
||||
import io.codearte.accurest.config.TestMode
|
||||
|
||||
class MainTest {
|
||||
public static void main(String[] args) {
|
||||
AccurestConfigProperties properties = new AccurestConfigProperties(
|
||||
contractsDslDir: new File('/home/devel/projects/codearte/accurest/accurest-core/src/test/resources/dsl'),
|
||||
generatedTestSourcesDir: new File('/tmp/accurest'),
|
||||
targetFramework: TestFramework.SPOCK, testMode: TestMode.MOCKMVC, basePackageForTests: 'io.test',
|
||||
staticImports: ['com.pupablada.Test.*'], imports: ['org.innapypa.Test'], excludedFiles: ["**/other"])
|
||||
println new TestGenerator(properties).generate()
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.codearte.accurest.builder
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
@CompileStatic
|
||||
class BookReturned implements Serializable {
|
||||
final String bookName
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
BookReturned(String bookName) {
|
||||
this.bookName = bookName
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package io.codearte.accurest.dsl
|
||||
|
||||
import com.github.tomakehurst.wiremock.stubbing.StubMapping
|
||||
import io.codearte.accurest.file.Contract
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
trait WireMockStubVerifier {
|
||||
|
||||
void stubMappingIsValidWireMockStub(String mappingDefinition) {
|
||||
StubMapping stubMapping = StubMapping.buildFrom(mappingDefinition)
|
||||
stubMapping.request.bodyPatterns.findAll { it.matches }.every {
|
||||
Pattern.compile(it.matches)
|
||||
}
|
||||
assert !mappingDefinition.contains('io.codearte.accurest.dsl.internal')
|
||||
}
|
||||
|
||||
void stubMappingIsValidWireMockStub(GroovyDsl contractDsl) {
|
||||
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.codearte.accurest.dsl.internal
|
||||
|
||||
import spock.lang.Specification
|
||||
|
||||
class ExecutionPropertySpec extends Specification {
|
||||
|
||||
def 'should insert passed value in place of $it placeholder'() {
|
||||
given:
|
||||
String commandToExecute = 'commandToExecute($it)'
|
||||
ExecutionProperty executionProperty = new ExecutionProperty(commandToExecute)
|
||||
and:
|
||||
String valueToInsert = 'someObject.itsValue'
|
||||
when:
|
||||
String commandWithInsertedValue = executionProperty.insertValue(valueToInsert)
|
||||
then:
|
||||
'commandToExecute(someObject.itsValue)' == commandWithInsertedValue
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method('PUT')
|
||||
headers {
|
||||
header 'Content-Type': 'application/json'
|
||||
}
|
||||
body("""\
|
||||
{
|
||||
"name": "Jan",
|
||||
"id": "${value(client('abc'), server('def'))}",
|
||||
}
|
||||
"""
|
||||
)
|
||||
url $(client('/[0-9]{2}'), server('/12'))
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
body("""\
|
||||
{
|
||||
"name": "Jan",
|
||||
"id": "${value(client('123'), server('321'))}",
|
||||
"surname": "${value(client('Kowalsky'), server('$checkIfSurnameValid($value)'))}"
|
||||
}
|
||||
"""
|
||||
)
|
||||
headers {
|
||||
header 'Content-Type': 'text/plain'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package io.codearte.accurest.plugin
|
||||
|
||||
import io.codearte.accurest.config.AccurestConfigProperties
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
/**
|
||||
* @author Jakub Kubrynski
|
||||
*/
|
||||
class AccurestGradlePlugin implements Plugin<Project> {
|
||||
|
||||
private static final String GENERATE_SERVER_TESTS_TASK_NAME = 'generateAccurest'
|
||||
private static final String DSL_TO_WIREMOCK_CLIENT_TASK_NAME = 'generateWireMockClientStubs'
|
||||
|
||||
private static final Class IDEA_PLUGIN_CLASS = org.gradle.plugins.ide.idea.IdeaPlugin
|
||||
private static final String GROUP_NAME = "Verification"
|
||||
|
||||
private Project project
|
||||
|
||||
@Override
|
||||
void apply(Project project) {
|
||||
this.project = project
|
||||
AccurestConfigProperties extension = project.extensions.create('accurest', AccurestConfigProperties)
|
||||
|
||||
project.check.dependsOn(GENERATE_SERVER_TESTS_TASK_NAME)
|
||||
|
||||
setConfigurationDefaults(extension)
|
||||
createGenerateTestsTask(extension)
|
||||
createAndConfigureGenerateWireMockClientStubsFromDslTask(extension)
|
||||
deprecatedCreateAndConfigureGenerateWiremockClientStubsFromDslTask()
|
||||
project.dependencies.add("testCompile", "com.github.tomakehurst:wiremock:2.0.10-beta")
|
||||
project.dependencies.add("testCompile", "com.toomuchcoding.jsonassert:jsonassert:${extension.getJsonAssertVersion()}")
|
||||
project.dependencies.add("testCompile", "org.assertj:assertj-core:2.3.0")
|
||||
|
||||
project.afterEvaluate {
|
||||
def hasIdea = project.plugins.findPlugin(IDEA_PLUGIN_CLASS)
|
||||
if (hasIdea) {
|
||||
project.idea {
|
||||
module {
|
||||
testSourceDirs += extension.generatedTestSourcesDir
|
||||
testSourceDirs += extension.contractsDslDir
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setConfigurationDefaults(AccurestConfigProperties extension) {
|
||||
extension.with {
|
||||
generatedTestSourcesDir = project.file("${project.buildDir}/generated-test-sources/accurest")
|
||||
contractsDslDir = defaultAccurestContractsDir() //TODO: Use sourceset
|
||||
basePackageForTests = 'io.codearte.accurest.tests'
|
||||
}
|
||||
}
|
||||
|
||||
private File defaultAccurestContractsDir() {
|
||||
project.file("${project.rootDir}/src/test/resources/accurest")
|
||||
}
|
||||
|
||||
private void createGenerateTestsTask(AccurestConfigProperties extension) {
|
||||
Task task = project.tasks.create(GENERATE_SERVER_TESTS_TASK_NAME, GenerateServerTestsTask)
|
||||
task.description = "Generate server tests from GroovyDSL"
|
||||
task.group = GROUP_NAME
|
||||
task.conventionMapping.with {
|
||||
contractsDslDir = { extension.contractsDslDir }
|
||||
generatedTestSourcesDir = { extension.generatedTestSourcesDir }
|
||||
configProperties = { extension }
|
||||
}
|
||||
}
|
||||
|
||||
private void createAndConfigureGenerateWireMockClientStubsFromDslTask(AccurestConfigProperties extension) {
|
||||
Task task = project.tasks.create(DSL_TO_WIREMOCK_CLIENT_TASK_NAME, GenerateWireMockClientStubsFromDslTask)
|
||||
task.description = "Generate WireMock client stubs from GroovyDSL"
|
||||
task.group = GROUP_NAME
|
||||
task.conventionMapping.with {
|
||||
contractsDslDir = { extension.contractsDslDir }
|
||||
stubsOutputDir = { extension.stubsOutputDir }
|
||||
configProperties = { extension }
|
||||
}
|
||||
}
|
||||
|
||||
private void deprecatedCreateAndConfigureGenerateWiremockClientStubsFromDslTask() {
|
||||
Task task = project.tasks.create('generateWiremockClientStubs')
|
||||
task.dependsOn('generateWireMockClientStubs')
|
||||
task.description = "DEPRECATED - Generates WireMock client stubs. - DEPRECATED - use 'generateWireMockClientStubs' task"
|
||||
task.group = GROUP_NAME
|
||||
task.doFirst {logger.warn("DEPRECATION WARNING. Task 'generateWiremockClientStubs' is deprecated. Use 'generateWireMockClientStubs' task instead.")}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package io.codearte.accurest.plugin
|
||||
|
||||
import io.codearte.accurest.AccurestException
|
||||
import io.codearte.accurest.TestGenerator
|
||||
import io.codearte.accurest.config.AccurestConfigProperties
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.internal.ConventionTask
|
||||
import org.gradle.api.tasks.InputDirectory
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
class GenerateServerTestsTask extends ConventionTask {
|
||||
|
||||
@InputDirectory
|
||||
File contractsDslDir
|
||||
@OutputDirectory
|
||||
File generatedTestSourcesDir
|
||||
|
||||
//TODO: How to deal with @Input*, @Output* and that domain object?
|
||||
AccurestConfigProperties configProperties
|
||||
|
||||
@TaskAction
|
||||
void generate() {
|
||||
project.logger.info("Accurest Plugin: Invoking test sources generation")
|
||||
|
||||
project.sourceSets.test.groovy {
|
||||
project.logger.info("Registering ${getConfigProperties().generatedTestSourcesDir} as test source directory")
|
||||
srcDir getConfigProperties().generatedTestSourcesDir
|
||||
}
|
||||
|
||||
try {
|
||||
//TODO: What with that? How to pass?
|
||||
TestGenerator generator = new TestGenerator(getConfigProperties())
|
||||
int generatedClasses = generator.generate()
|
||||
project.logger.info("Generated {} test classes", generatedClasses)
|
||||
} catch (AccurestException e) {
|
||||
throw new GradleException("Accurest Plugin exception: ${e.message}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package io.codearte.accurest.plugin
|
||||
|
||||
import io.codearte.accurest.config.AccurestConfigProperties
|
||||
import io.codearte.accurest.wiremock.DslToWireMockClientConverter
|
||||
import io.codearte.accurest.wiremock.RecursiveFilesConverter
|
||||
import org.gradle.api.internal.ConventionTask
|
||||
import org.gradle.api.tasks.InputDirectory
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
//TODO: Implement as an incremental task: https://gradle.org/docs/current/userguide/custom_tasks.html#incremental_tasks ?
|
||||
class GenerateWireMockClientStubsFromDslTask extends ConventionTask {
|
||||
|
||||
@InputDirectory
|
||||
File contractsDslDir
|
||||
@OutputDirectory
|
||||
File stubsOutputDir
|
||||
|
||||
AccurestConfigProperties configProperties
|
||||
|
||||
@TaskAction
|
||||
void generate() {
|
||||
logger.info("Accurest Plugin: Invoking GroovyDSL to WireMock client stubs conversion")
|
||||
logger.debug("From '${getContractsDslDir()}' to '${getStubsOutputDir()}'")
|
||||
RecursiveFilesConverter converter = new RecursiveFilesConverter(new DslToWireMockClientConverter(), getConfigProperties())
|
||||
converter.processFiles()
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
implementation-class=io.codearte.accurest.plugin.AccurestGradlePlugin
|
||||
@@ -1,22 +0,0 @@
|
||||
package io.codearte.accurest.plugin
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.testfixtures.ProjectBuilder
|
||||
import spock.lang.Ignore
|
||||
import spock.lang.Specification
|
||||
|
||||
/**
|
||||
* @author Jakub Kubrynski
|
||||
*/
|
||||
@Ignore
|
||||
class AccurestGradlePluginTest extends Specification {
|
||||
|
||||
def void greeterPluginAddsGreetingTaskToProject() {
|
||||
when:
|
||||
Project project = ProjectBuilder.builder().build()
|
||||
project.apply plugin: 'accurest'
|
||||
|
||||
then:
|
||||
project.tasks.generateAccurest
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package io.codearte.accurest.plugin
|
||||
|
||||
import spock.lang.Stepwise
|
||||
|
||||
@Stepwise
|
||||
class MessagingProjectSpec extends AccurestIntegrationSpec {
|
||||
|
||||
def setup() {
|
||||
setupForProject("functionalTest/messagingProject")
|
||||
runTasksSuccessfully('clean') //delete accidental output when previously importing SimpleBoot into Idea to tweak it
|
||||
}
|
||||
|
||||
def "should pass basic flow for Spock"() {
|
||||
given:
|
||||
assert fileExists('build.gradle')
|
||||
expect:
|
||||
runTasksSuccessfully('check', "publishToMavenLocal")
|
||||
jarContainsAccurestContracts('build/libs')
|
||||
}
|
||||
|
||||
def "should pass basic flow for JUnit"() {
|
||||
given:
|
||||
runTasksSuccessfully('clean')
|
||||
assert fileExists('build.gradle')
|
||||
expect:
|
||||
switchToJunitTestFramework('io.codearte.accurest.samples.book.MessagingBaseSpec', 'io.codearte.accurest.samples.book.MessagingBaseTest')
|
||||
runTasksSuccessfully('check', "publishToMavenLocal")
|
||||
jarContainsAccurestContracts('build/libs')
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package io.codearte.accurest.plugin
|
||||
|
||||
import spock.lang.Stepwise
|
||||
|
||||
@Stepwise
|
||||
class SampleJerseyProjectSpec extends AccurestIntegrationSpec {
|
||||
|
||||
def setup() {
|
||||
setupForProject("functionalTest/sampleJerseyProject")
|
||||
runTasksSuccessfully('clean') //delete accidental output when previously importing SimpleBoot into Idea to tweak it
|
||||
}
|
||||
|
||||
def "should pass basic flow for Spock"() {
|
||||
given:
|
||||
assert fileExists('build.gradle')
|
||||
expect:
|
||||
runTasksSuccessfully('check', "publishToMavenLocal")
|
||||
jarContainsAccurestContracts('fraudDetectionService/build/libs')
|
||||
}
|
||||
|
||||
def "should pass basic flow for JUnit"() {
|
||||
given:
|
||||
switchToJunitTestFramework()
|
||||
assert fileExists('build.gradle')
|
||||
expect:
|
||||
runTasksSuccessfully('check', "publishToMavenLocal")
|
||||
jarContainsAccurestContracts('fraudDetectionService/build/libs')
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package io.codearte.accurest.plugin
|
||||
|
||||
import spock.lang.Stepwise
|
||||
|
||||
@Stepwise
|
||||
class SampleProjectSpec extends AccurestIntegrationSpec {
|
||||
|
||||
def setup() {
|
||||
setupForProject("functionalTest/sampleProject")
|
||||
runTasksSuccessfully('clean') //delete accidental output when previously importing SimpleBoot into Idea to tweak it
|
||||
}
|
||||
|
||||
def "should pass basic flow for Spock"() {
|
||||
given:
|
||||
assert fileExists('build.gradle')
|
||||
expect:
|
||||
runTasksSuccessfully('check', "publishToMavenLocal")
|
||||
jarContainsAccurestContracts('fraudDetectionService/build/libs')
|
||||
}
|
||||
|
||||
def "should pass basic flow for JUnit"() {
|
||||
given:
|
||||
switchToJunitTestFramework()
|
||||
assert fileExists('build.gradle')
|
||||
expect:
|
||||
runTasksSuccessfully('check', "publishToMavenLocal")
|
||||
jarContainsAccurestContracts('fraudDetectionService/build/libs')
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package io.codearte.accurest.plugin
|
||||
|
||||
import spock.lang.Stepwise
|
||||
|
||||
@Stepwise
|
||||
class ScenarioProjectSpec extends AccurestIntegrationSpec {
|
||||
|
||||
def setup() {
|
||||
setupForProject("functionalTest/scenarioProject")
|
||||
runTasksSuccessfully('clean') //delete accidental output when previously importing SimpleBoot into Idea to tweak it
|
||||
}
|
||||
|
||||
def "should pass basic flow for Spock"() {
|
||||
given:
|
||||
assert fileExists('build.gradle')
|
||||
expect:
|
||||
runTasksSuccessfully('check', "publishToMavenLocal")
|
||||
jarContainsAccurestContracts('fraudDetectionService/build/libs')
|
||||
}
|
||||
|
||||
def "should pass basic flow for JUnit"() {
|
||||
given:
|
||||
assert fileExists('build.gradle')
|
||||
expect:
|
||||
switchToJunitTestFramework()
|
||||
runTasksSuccessfully('check', "publishToMavenLocal")
|
||||
jarContainsAccurestContracts('fraudDetectionService/build/libs')
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
groupId=com.ofg
|
||||
jacksonMapper=1.9.13
|
||||
restAssuredVersion=2.4.0
|
||||
springVersion=4.1.7.RELEASE
|
||||
|
||||
springBootVersion=1.3.3.RELEASE
|
||||
@@ -1,6 +0,0 @@
|
||||
#Sat Feb 21 20:13:29 CET 2015
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip
|
||||
@@ -1,18 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
priority 2
|
||||
request {
|
||||
method 'PUT'
|
||||
url '/api/12'
|
||||
headers {
|
||||
header 'Content-Type': 'application/json'
|
||||
}
|
||||
body '''\
|
||||
[{
|
||||
"text": "Gonna see you at Warsaw"
|
||||
}]
|
||||
'''
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method 'PUT'
|
||||
url $(client(regex('^/api/[0-9]{2}$')), server('/api/12'))
|
||||
headers {
|
||||
header 'Content-Type': 'application/json'
|
||||
}
|
||||
body '''\
|
||||
[{
|
||||
"text": "Gonna see you at Warsaw"
|
||||
}]
|
||||
'''
|
||||
}
|
||||
response {
|
||||
headers {
|
||||
header 'Content-Type': $(client('application/json'), server(regex('application/json.*')))
|
||||
header 'Location': $(client('https://localhost:8080'), server(execute('isEmpty($it)')))
|
||||
}
|
||||
body (
|
||||
path: $(client('/api/12'), server(regex('^/api/[0-9]{2}$'))),
|
||||
correlationId: $(client('1223456'), server(execute('isProperCorrelationId($it)')))
|
||||
)
|
||||
status 200
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
rootProject.name='bootSimple'
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.ofg.twitter.places
|
||||
|
||||
import com.ofg.twitter.place.PairIdController
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders
|
||||
import spock.lang.Specification
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
|
||||
|
||||
class AcceptanceSpec extends Specification {
|
||||
|
||||
def "should have controller up and running"() {
|
||||
given:
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new PairIdController()).build()
|
||||
expect:
|
||||
mockMvc.perform(put("/api/${1}").
|
||||
contentType(MediaType.APPLICATION_JSON).
|
||||
content("""[{"text":"Gonna see you at Warsaw"}]""")).
|
||||
andExpect(status().isOk())
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.ofg.twitter.places
|
||||
|
||||
import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc
|
||||
import com.ofg.twitter.place.PairIdController
|
||||
import spock.lang.Specification
|
||||
|
||||
// tag::base_class[]
|
||||
abstract class BaseMockMvcSpec extends Specification {
|
||||
|
||||
def setup() {
|
||||
RestAssuredMockMvc.standaloneSetup(new PairIdController())
|
||||
}
|
||||
|
||||
void isProperCorrelationId(Integer correlationId) {
|
||||
assert correlationId == 123456
|
||||
}
|
||||
|
||||
void isEmpty(String value) {
|
||||
assert value == null
|
||||
}
|
||||
|
||||
}
|
||||
// end::base_class[]
|
||||
@@ -1,14 +0,0 @@
|
||||
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
|
||||
import ch.qos.logback.core.ConsoleAppender
|
||||
|
||||
String console = "CONSOLE"
|
||||
String logPattern = "%d{yyyy-MM-dd HH:mm:ss.SSSZ, Europe/Warsaw} | %-5level | %X{correlationId} | %thread | %logger{1} | %m%n"
|
||||
|
||||
appender(console, ConsoleAppender) {
|
||||
encoder(PatternLayoutEncoder) {
|
||||
pattern = logPattern
|
||||
}
|
||||
}
|
||||
|
||||
root(INFO, [console])
|
||||
logger("com.ofg", DEBUG)
|
||||
@@ -1,6 +0,0 @@
|
||||
groupId=io.codearte
|
||||
jacksonMapper=1.9.13
|
||||
restAssuredVersion=2.9.0
|
||||
springVersion=4.2.3.RELEASE
|
||||
|
||||
springBootVersion=1.3.3.RELEASE
|
||||
@@ -1,6 +0,0 @@
|
||||
#Sun Apr 17 20:31:11 CEST 2016
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip
|
||||
@@ -1,10 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
url '/foo'
|
||||
method 'GET'
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
body 'bar'
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
label 'some_label'
|
||||
input {
|
||||
messageFrom('delete')
|
||||
messageBody([
|
||||
bookName: 'foo'
|
||||
])
|
||||
messageHeaders {
|
||||
header('sample', 'header')
|
||||
}
|
||||
assertThat('bookWasDeleted()')
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
label 'some_label'
|
||||
input {
|
||||
triggeredBy('bookReturnedTriggered()')
|
||||
}
|
||||
outputMessage {
|
||||
sentTo('output')
|
||||
body('''{ "bookName" : "foo" }''')
|
||||
headers {
|
||||
header('BOOK-NAME', 'foo')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
label 'some_label'
|
||||
input {
|
||||
messageFrom('input')
|
||||
messageBody([
|
||||
bookName: 'foo'
|
||||
])
|
||||
messageHeaders {
|
||||
header('sample', 'header')
|
||||
}
|
||||
}
|
||||
outputMessage {
|
||||
sentTo('output')
|
||||
body([
|
||||
bookName: 'foo'
|
||||
])
|
||||
headers {
|
||||
header('BOOK-NAME', 'foo')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
rootProject.name='bootSimple'
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.codearte.accurest.samples.book
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
@CompileStatic
|
||||
class BookDeleted {
|
||||
final String bookName
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
BookDeleted(String bookName) {
|
||||
this.bookName = bookName
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.codearte.accurest.samples.book
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
@CompileStatic
|
||||
class BookReturned {
|
||||
final String bookName
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
BookReturned(String bookName) {
|
||||
this.bookName = bookName
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package io.codearte.accurest.samples.book
|
||||
|
||||
import org.springframework.boot.SpringApplication
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.context.annotation.ImportResource
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@SpringBootApplication
|
||||
@RestController
|
||||
@ImportResource("classpath*:integration-context.xml")
|
||||
class IntegrationMessagingApplication {
|
||||
|
||||
@RequestMapping("/foo")
|
||||
String foo() {
|
||||
return "bar"
|
||||
}
|
||||
|
||||
static void main(String[] args) {
|
||||
SpringApplication.run(IntegrationMessagingApplication.class, args)
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method """PUT"""
|
||||
url """/fraudcheck"""
|
||||
body("""
|
||||
{
|
||||
"clientPesel":"${value(client(regex('[0-9]{10}')), server('1234567890'))}",
|
||||
"loanAmount":99999}
|
||||
"""
|
||||
)
|
||||
headers {
|
||||
header("""Content-Type""", """application/vnd.fraud.v1+json""")
|
||||
}
|
||||
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
body( """{
|
||||
"fraudCheckStatus": "${value(client('FRAUD'), server(regex('[A-Z]{5}')))}",
|
||||
"rejectionReason": "Amount too high"
|
||||
}""")
|
||||
headers {
|
||||
header('Content-Type': 'application/vnd.fraud.v1+json')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method 'PUT'
|
||||
url '/fraudcheck'
|
||||
body("""
|
||||
{
|
||||
"clientPesel":"${value(client(regex('[0-9]{10}')), server('1234567890'))}",
|
||||
"loanAmount":123.123
|
||||
}
|
||||
"""
|
||||
)
|
||||
headers {
|
||||
header('Content-Type', 'application/vnd.fraud.v1+json')
|
||||
}
|
||||
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
body(
|
||||
fraudCheckStatus: "OK",
|
||||
rejectionReason: $(client(null), server(execute('assertThatRejectionReasonIsNull($it)')))
|
||||
)
|
||||
headers {
|
||||
header('Content-Type': 'application/vnd.fraud.v1+json')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.blogspot.toomuchcoding.frauddetection.model;
|
||||
|
||||
public enum FraudCheckStatus {
|
||||
OK, FRAUD
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#Wed Jan 28 00:32:44 CET 2015
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.blogspot.toomuchcoding.frauddetection.model;
|
||||
|
||||
public class Client {
|
||||
|
||||
private String pesel;
|
||||
|
||||
public String getPesel() {
|
||||
return pesel;
|
||||
}
|
||||
|
||||
public void setPesel(String pesel) {
|
||||
this.pesel = pesel;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.blogspot.toomuchcoding.frauddetection.model;
|
||||
|
||||
public enum FraudCheckStatus {
|
||||
OK, FRAUD
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.blogspot.toomuchcoding.frauddetection.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class FraudServiceRequest {
|
||||
|
||||
private String clientPesel;
|
||||
|
||||
private BigDecimal loanAmount;
|
||||
|
||||
public FraudServiceRequest() {
|
||||
}
|
||||
|
||||
public FraudServiceRequest(LoanApplication loanApplication) {
|
||||
this.clientPesel = loanApplication.getClient().getPesel();
|
||||
this.loanAmount = loanApplication.getAmount();
|
||||
}
|
||||
|
||||
public String getClientPesel() {
|
||||
return clientPesel;
|
||||
}
|
||||
|
||||
public void setClientPesel(String clientPesel) {
|
||||
this.clientPesel = clientPesel;
|
||||
}
|
||||
|
||||
public BigDecimal getLoanAmount() {
|
||||
return loanAmount;
|
||||
}
|
||||
|
||||
public void setLoanAmount(BigDecimal loanAmount) {
|
||||
this.loanAmount = loanAmount;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.blogspot.toomuchcoding.frauddetection.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class LoanApplication {
|
||||
|
||||
private Client client;
|
||||
|
||||
private BigDecimal amount;
|
||||
|
||||
private String loanApplicationId;
|
||||
|
||||
public Client getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void setClient(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(BigDecimal amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public String getLoanApplicationId() {
|
||||
return loanApplicationId;
|
||||
}
|
||||
|
||||
public void setLoanApplicationId(String loanApplicationId) {
|
||||
this.loanApplicationId = loanApplicationId;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
include ':fraudDetectionService'
|
||||
include ':loanApplicationService'
|
||||
@@ -1,27 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method """PUT"""
|
||||
url """/fraudcheck"""
|
||||
body("""
|
||||
{
|
||||
"clientPesel":"${value(client(regex('[0-9]{10}')), server('1234567890'))}",
|
||||
"loanAmount":99999}
|
||||
"""
|
||||
)
|
||||
headers {
|
||||
header("""Content-Type""", """application/vnd.fraud.v1+json""")
|
||||
}
|
||||
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
body( """{
|
||||
"fraudCheckStatus": "${value(client('FRAUD'), server(regex('[A-Z]{5}')))}",
|
||||
"rejectionReason": "Amount too high"
|
||||
}""")
|
||||
headers {
|
||||
header('Content-Type': 'application/vnd.fraud.v1+json')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
io.codearte.accurest.dsl.GroovyDsl.make {
|
||||
request {
|
||||
method 'PUT'
|
||||
url '/fraudcheck'
|
||||
body("""
|
||||
{
|
||||
"clientPesel":"${value(client(regex('[0-9]{10}')), server('1234567890'))}",
|
||||
"loanAmount":123.123
|
||||
}
|
||||
"""
|
||||
)
|
||||
headers {
|
||||
header('Content-Type', 'application/vnd.fraud.v1+json')
|
||||
}
|
||||
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
body(
|
||||
fraudCheckStatus: "OK",
|
||||
rejectionReason: $(client(null), server(execute('assertThatRejectionReasonIsNull($it)')))
|
||||
)
|
||||
headers {
|
||||
header('Content-Type': 'application/vnd.fraud.v1+json')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user