diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/config/AccurestConfigProperties.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/config/AccurestConfigProperties.groovy index 253887ae7b..53567ed1a2 100644 --- a/accurest-core/src/main/groovy/io/codearte/accurest/config/AccurestConfigProperties.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/config/AccurestConfigProperties.groovy @@ -75,8 +75,4 @@ class AccurestConfigProperties { */ File stubsOutputDir - /** - * Which version of Accurest Messaging Core to use - */ - String accurestMessagingCoreVersion = "+" } diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/builder/ContractHttpDocsSpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/builder/ContractHttpDocsSpec.groovy index 235e8184b5..d8610d92a9 100644 --- a/accurest-core/src/test/groovy/io/codearte/accurest/builder/ContractHttpDocsSpec.groovy +++ b/accurest-core/src/test/groovy/io/codearte/accurest/builder/ContractHttpDocsSpec.groovy @@ -232,8 +232,7 @@ class ContractHttpDocsSpec extends Specification { header 'Content-Type': 'application/json' } body( - code: value(stub("123123"), test(optional("123123"))), - message: "User not found by email == [${value(test(regex(email())), stub('not.existing@user.com'))}]" + code: value(stub("123123"), test(optional("123123"))) ) } } @@ -244,28 +243,27 @@ class ContractHttpDocsSpec extends Specification { BlockBuilder blockBuilder = new BlockBuilder(" ") new MockMvcSpockMethodRequestProcessingBodyBuilder(optionals).appendTo(blockBuilder) expect: - stripped(blockBuilder.toString()) == stripped( + String expectedTest = // tag::optionals_test[] """ -given: - def request = given() - .header('Content-Type', 'application/json') - .body('''{"email":"abc@abc.com","callback_url":"http://partners.com"}''') + given: + def request = given() + .header('Content-Type', 'application/json') + .body('''{"email":"abc@abc.com","callback_url":"http://partners.com"}''') -when: - def response = given().spec(request) - .post("/users/password") + when: + def response = given().spec(request) + .post("/users/password") -then: - response.statusCode == 404 - response.header('Content-Type') == 'application/json' -and: - DocumentContext parsedJson = JsonPath.parse(response.body.asString()) - assertThatJson(parsedJson).field("message").matches("User not found by email == \\\\\\\\[[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\\\\\.[a-zA-Z]{2,4}\\\\\\\\]") - assertThatJson(parsedJson).field("code").matches("(123123)?") + then: + response.statusCode == 404 + response.header('Content-Type') == 'application/json' + and: + DocumentContext parsedJson = JsonPath.parse(response.body.asString()) + assertThatJson(parsedJson).field("code").matches("(123123)?") """ // end::optionals_test[] -) + stripped(blockBuilder.toString()) == stripped(expectedTest) } GroovyDsl method = @@ -294,6 +292,6 @@ and: // end::method[] private String stripped(String string) { - return string.stripMargin().stripIndent().replace('\t', '').replace('\n', '') + return string.stripMargin().stripIndent().replace('\t', '').replace('\n', '').replace(' ','') } } diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/builder/JaxRsClientMethodBuilderSpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/builder/JaxRsClientMethodBuilderSpec.groovy index 3d36d7676f..59a33c47c1 100644 --- a/accurest-core/src/test/groovy/io/codearte/accurest/builder/JaxRsClientMethodBuilderSpec.groovy +++ b/accurest-core/src/test/groovy/io/codearte/accurest/builder/JaxRsClientMethodBuilderSpec.groovy @@ -615,8 +615,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub status 200 body """ { - "property1": "a", - "property2": "b" + "property1": "a" } """ } @@ -627,8 +626,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - stripped(test) == stripped( // tag::jaxrs[] - ''' + String expectedResponse = +// tag::jaxrs[] +''' // when: Response response = webTarget .path("/users") @@ -650,15 +650,14 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub // and: DocumentContext parsedJson = JsonPath.parse(responseAsString); assertThatJson(parsedJson).field("property1").isEqualTo("a"); - assertThatJson(parsedJson).field("property2").isEqualTo("b"); ''' // end::jaxrs[] -) + stripped(test) == stripped(expectedResponse) and: stubMappingIsValidWireMockStub(contractDsl) } private String stripped(String string) { - return string.stripMargin().stripIndent().replace('\t', '').replace('\n', '') + return string.stripMargin().stripIndent().replace('\t', '').replace('\n', '').replace(' ','') } } diff --git a/accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/AccurestGradlePlugin.groovy b/accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/AccurestGradlePlugin.groovy index bf0edc316e..9709541e2d 100644 --- a/accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/AccurestGradlePlugin.groovy +++ b/accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/AccurestGradlePlugin.groovy @@ -38,6 +38,7 @@ class AccurestGradlePlugin implements Plugin { project.idea { module { testSourceDirs += extension.generatedTestSourcesDir + testSourceDirs += extension.contractsDslDir } } } @@ -47,11 +48,15 @@ class AccurestGradlePlugin implements Plugin { void setConfigurationDefaults(AccurestConfigProperties extension) { extension.with { generatedTestSourcesDir = project.file("${project.buildDir}/generated-test-sources/accurest") - contractsDslDir = project.file("${project.rootDir}/src/test/accurest") //TODO: Use sourceset + contractsDslDir = defaultAccurestContractsDir() //TODO: Use sourceset basePackageForTests = 'io.codearte.accurest.tests' } } + private File defaultAccurestContractsDir() { + project.file("${project.rootDir}/src/test/accurest") + } + private void createGenerateTestsTask(AccurestConfigProperties extension) { Task task = project.tasks.create(GENERATE_SERVER_TESTS_TASK_NAME, GenerateServerTestsTask) task.description = "Generate server tests from GroovyDSL" diff --git a/docs/src/docs/asciidoc/contract.adoc b/docs/src/docs/asciidoc/contract.adoc index 000082923e..a028da70cb 100644 --- a/docs/src/docs/asciidoc/contract.adoc +++ b/docs/src/docs/asciidoc/contract.adoc @@ -158,4 +158,33 @@ Example of a test API generated: [source,groovy,indent=0] ---- include::../../../../accurest-core/src/test/groovy/io/codearte/accurest/builder/JaxRsClientMethodBuilderSpec.groovy[tags=jaxrs,indent=0] ----- \ No newline at end of file +---- + +=== Messaging Top-Level Elements + +The DSL for messaging looks a little bit different than the one that focuses on HTTP. + +==== Output triggered by a method + +The output message can be triggered by calling a method (e.g. a Scheduler was started and a message was sent) + +[source,groovy] +---- +include::../../../../samples/messaging-integration/src/test/groovy/io/codearte/accurest/samples/messaging/IntegrationMessagingApplicationSpec.groovy[tags=method_trigger,indent=0] +---- + +In this case the output message will be sent to `output` if a method called `bookReturnedTriggered` will be executed. In the message *publisher's* side +we will generate a test that will call that method to trigger the message. On the *consumer* side you can use the `some_label` to trigger the message. + +==== Output triggered by a message + +The output message can be triggered by receiving a message. + +[source,groovy] +---- +include::../../../../samples/messaging-integration/src/test/groovy/io/codearte/accurest/samples/messaging/IntegrationMessagingApplicationSpec.groovy[tags=message_trigger,indent=0] +---- + +In this case the output message will be sent to `output` if a proper message will be received on the `input` destination. In the message *publisher's* side +we will generate a test that will send the input message to the defined destination. On the *consumer* side you can either send a message to the input +destination or use the `some_label` to trigger the message. \ No newline at end of file diff --git a/docs/src/docs/asciidoc/index.adoc b/docs/src/docs/asciidoc/index.adoc index 060f611643..2cd9d4ea76 100644 --- a/docs/src/docs/asciidoc/index.adoc +++ b/docs/src/docs/asciidoc/index.adoc @@ -1,5 +1,3 @@ -Welcome to the Accurest Documentation! - include::introduction.adoc[] include::contract.adoc[] diff --git a/docs/src/docs/asciidoc/introduction.adoc b/docs/src/docs/asciidoc/introduction.adoc index f7ac2b0c17..07808673b8 100644 --- a/docs/src/docs/asciidoc/introduction.adoc +++ b/docs/src/docs/asciidoc/introduction.adoc @@ -99,12 +99,22 @@ Accurest and Stub Runner are using the following libraries - https://github.com/jayway/JsonPath[Jayway JSONPath] - https://github.com/marcingrzejszczak/jsonassert[JSONAssert from Marcin Grzejszczak] -=== Additional readings / videos +=== Additional links Below you can find some resources related to Accurest and Stub Runner. Note that some can be outdated since the Accurest project is under constant development. -- https://www.youtube.com/watch?v=daafmTYFoDU[Olga Maciaszek-Sharma talking about Accurest] -- https://vimeo.com/130779882[Marcin Grzejszczak and Jakub Kubrynski talking about Accurest] +==== Videos + +*Olga Maciaszek-Sharma talking about Accurest* + +video::daafmTYFoDU[youtube] + +*Marcin Grzejszczak and Jakub Kubrynski talking about Accurest* + +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 article from Marcin Grzejszczak's blog] +- http://toomuchcoding.com/blog/categories/accurest/[Accurest related articles from Marcin Grzejszczak's blog] diff --git a/docs/src/docs/asciidoc/rest.adoc b/docs/src/docs/asciidoc/rest.adoc index d17bf16a7c..ade4477aa9 100644 --- a/docs/src/docs/asciidoc/rest.adoc +++ b/docs/src/docs/asciidoc/rest.adoc @@ -15,7 +15,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'io.codearte.accurest:accurest-gradle-plugin:1.0.6' + classpath 'io.codearte.accurest:accurest-gradle-plugin:${accurest_version}' } } @@ -23,7 +23,7 @@ apply plugin: 'groovy' apply plugin: 'accurest' dependencies { - testCompile('org.codehaus.groovy:groovy-all:2.4.6') + testCompile 'org.codehaus.groovy:groovy-all:2.4.6' testCompile 'org.spockframework:spock-core:1.0-groovy-2.4' testCompile 'com.jayway.restassured:spring-mock-mvc:2.9.0' // needed if you're going to use Spring MockMvc } @@ -53,7 +53,8 @@ Read more: http://codearte.github.io/accurest-maven-plugin/[accurest-maven-plugi ===== Add stubs -By default Accurest is looking for stubs in src/test/resources/stubs directory. +By default Accurest is looking for stubs in `src/test/resources/stubs` directory. + Directory containing stub definitions is treated as a class name, and each stub definition is treated as a single test. We assume that it contains at least one directory which will be used as test class name. If there is more than one level of nested directories all except the last one will be used as package name. So with following structure @@ -65,8 +66,8 @@ src/test/accurest/myservice/shouldReturnUser.groovy ---- Accurest will create test class `defaultBasePackage.MyService` with two methods - - shouldCreateUser() - - shouldReturnUser() + - `shouldCreateUser()` + - `shouldReturnUser()` ==== Run plugin @@ -105,29 +106,32 @@ accurest { [source,groovy,indent=0] ---- -package org.mycompany.tests - -import org.mycompany.ExampleSpringController -import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc -import spock.lang.Specification - -class MvcSpec extends Specification { - def setup() { - RestAssuredMockMvc.standaloneSetup(new ExampleSpringController()) - } -} +include::../../../../accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/com/ofg/twitter/places/BaseMockMvcSpec.groovy[tags=base_class,indent=0] ---- -In case of using `Explicit` mode, you can use base class to initialize the whole tested app similarly as in regular integration tests. In case of `JAXRSCLIENT` mode this base class should also contain `protected WebTarget webTarget` field, right now the only option to test JAX-RS API is to start a web server. +In case of using `Explicit` mode, you can use base class to initialize the whole tested app similarly as in regular integration tests. In case of `JAXRSCLIENT` mode this base class +should also contain `protected WebTarget webTarget` field, right now the only option to test JAX-RS API is to start a web server. ==== Invoking generated tests To ensure that provider side is complaint with defined contracts, you need to invoke: -`./gradlew generateAccurest test` + +[source,bash,indent=0] +---- +./gradlew generateAccurest test +---- ==== Accurest on consumer side -In consumer service you need to configure Accurest plugin in exactly the same way as in case of provider. You need to copy contracts stored in src/test/resources/stubs and generate Wiremock json stubs using: `./gradlew generateWireMockClientStubs` command. Note that `stubsOutputDir` option has to be set for stub generation to work. +In consumer service you need to configure Accurest plugin in exactly the same way as in case of provider. If you don't want to use Stub Runner then you need to copy contracts stored in +`src/test/accurest` and generate WireMock json stubs using: + +[source,bash,indent=0] +---- +./gradlew generateWireMockClientStubs +---- + +command. Note that `stubsOutputDir` option has to be set for stub generation to work. When present, json stubs can be used in consumer automated tests. diff --git a/docs/src/docs/asciidoc/stubrunner_msg.adoc b/docs/src/docs/asciidoc/stubrunner_msg.adoc index 2548584162..482dae2e01 100644 --- a/docs/src/docs/asciidoc/stubrunner_msg.adoc +++ b/docs/src/docs/asciidoc/stubrunner_msg.adoc @@ -10,34 +10,6 @@ Stub Runner has the functionality to run the published stubs in memory. It can i It also provides points of entry to integrate with any other solution on the market. -=== DSL - -The DSL for messaging looks a little bit different than the one that focuses on HTTP. - -==== Output triggered by a method - -The output message can be triggered by calling a method (e.g. a Scheduler was started and a message was sent) - -[source,groovy] ----- -include::../../../../samples/messaging-integration/src/test/groovy/io/codearte/accurest/samples/messaging/IntegrationMessagingApplicationSpec.groovy[tags=method_trigger,indent=0] ----- - -In this case the output message will be sent to `output` if a method called `bookReturnedTriggered` will be executed. In the message *publisher's* side -we will generate a test that will call that method to trigger the message. On the *consumer* side you can use the `some_label` to trigger the message. - -==== Output triggered by a message - -The output message can be triggered by receiving a message. - -[source,groovy] ----- -include::../../../../samples/messaging-integration/src/test/groovy/io/codearte/accurest/samples/messaging/IntegrationMessagingApplicationSpec.groovy[tags=message_trigger,indent=0] ----- - -In this case the output message will be sent to `output` if a proper message will be received on the `input` destination. In the message *publisher's* side -we will generate a test that will send the input message to the defined destination. On the *consumer* side you can either send a message to the input -destination or use the `some_label` to trigger the message. === Stub triggering