From 9954efdf28a5b8dbb78cab02a1a0842341d6ae1f Mon Sep 17 00:00:00 2001 From: Tim Ysewyn Date: Sat, 10 Aug 2019 17:51:13 +0200 Subject: [PATCH] Made DSL less error prone --- .../fraudname/shouldReturnACookie.kts | 10 +- .../contract/spec/internal/BodyMatcherDsl.kt | 30 --- .../contract/spec/internal/BodyMatchersDsl.kt | 28 +- .../cloud/contract/spec/internal/CookieDsl.kt | 29 -- .../contract/spec/internal/CookiesDsl.kt | 14 +- .../cloud/contract/spec/internal/HeaderDsl.kt | 29 -- .../contract/spec/internal/HeadersDsl.kt | 14 +- .../cloud/contract/spec/ContractTests.kt | 250 ++---------------- 8 files changed, 44 insertions(+), 360 deletions(-) delete mode 100644 specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/BodyMatcherDsl.kt delete mode 100644 specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookieDsl.kt delete mode 100644 specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/HeaderDsl.kt diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.kts b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.kts index 4ba135dc42..98f6d253db 100644 --- a/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.kts +++ b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.kts @@ -24,14 +24,8 @@ contract { method = GET url = url("/frauds/name") cookies { - cookie { - name = "name" - value = "foo" - } - cookie{ - name = "name2" - value = "bar" - } + cookie("name", "foo") + cookie("name2", "bar") } } response { diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/BodyMatcherDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/BodyMatcherDsl.kt deleted file mode 100644 index dea3f6fac2..0000000000 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/BodyMatcherDsl.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.spec.internal - -import kotlin.properties.Delegates - -/** - * @author Tim Ysewyn - */ -class BodyMatcherDsl { - - var path: String by Delegates.notNull() - - var matcher: MatchingTypeValue by Delegates.notNull() - -} \ No newline at end of file diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/BodyMatchersDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/BodyMatchersDsl.kt index 2afb340154..12a497d5df 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/BodyMatchersDsl.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/BodyMatchersDsl.kt @@ -27,31 +27,23 @@ open class BodyMatchersDsl { private val xPathMatchers = LinkedHashMap() /** - * Adds and configures a JSON path matcher. + * Adds a JSON path matcher. * - * @param configurer The lambda to configure the JSON path matcher. + * @param path The path. + * @param matcher The matcher. */ - fun jsonPath(configurer: BodyMatcherDsl.() -> Unit) { - try { - val bodyMatcher = BodyMatcherDsl().apply(configurer) - this.jsonPathMatchers[bodyMatcher.path] = bodyMatcher.matcher - } catch (ex: IllegalStateException) { - throw IllegalStateException("Body matcher is missing its path or matcher") - } + fun jsonPath(path: String, matcher: MatchingTypeValue) { + this.jsonPathMatchers[path] = matcher } /** - * Adds and configures a xPath matcher. + * Adds an xPath matcher. * - * @param configurer The lambda to configure the xPath matcher. + * @param path The path. + * @param matcher The matcher. */ - fun xPath(configurer: BodyMatcherDsl.() -> Unit) { - try { - val bodyMatcher = BodyMatcherDsl().apply(configurer) - this.jsonPathMatchers[bodyMatcher.path] = bodyMatcher.matcher - } catch (ex: IllegalStateException) { - throw IllegalStateException("Body matcher is missing its path or matcher") - } + fun xPath(path: String, matcher: MatchingTypeValue) { + this.xPathMatchers[path] = matcher } fun byDate() = MatchingTypeValue(MatchingType.DATE, RegexPatterns.isoDate()) diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookieDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookieDsl.kt deleted file mode 100644 index da71232d76..0000000000 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookieDsl.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.spec.internal - -import kotlin.properties.Delegates - -/** - * @author Tim Ysewyn - */ -class CookieDsl { - - var name: String by Delegates.notNull() - - var value: Any by Delegates.notNull() -} diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookiesDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookiesDsl.kt index de6f34cd98..b987bc5a71 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookiesDsl.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookiesDsl.kt @@ -26,17 +26,13 @@ open class CookiesDsl : CommonDsl() { open fun matching(value: Any?): Any? = value /** - * Adds and configures a cookie. + * Adds a cookie. * - * @param configurer The lambda to configure the cookie. + * @param name The name of the cookie. + * @param value The value of the cookie. */ - fun cookie(configurer: CookieDsl.() -> Unit) { - try { - val cookie = CookieDsl().apply(configurer) - this.cookies[cookie.name] = cookie.value - } catch (ex: IllegalStateException) { - throw IllegalStateException("Cookie is missing its name or value") - } + fun cookie(name: String, value: Any) { + this.cookies[name] = value } internal fun get(): Cookies { diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/HeaderDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/HeaderDsl.kt deleted file mode 100644 index 618aae10f7..0000000000 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/HeaderDsl.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.spec.internal - -import kotlin.properties.Delegates - -/** - * @author Tim Ysewyn - */ -class HeaderDsl { - - var name: String by Delegates.notNull() - - var value: Any by Delegates.notNull() -} \ No newline at end of file diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/HeadersDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/HeadersDsl.kt index e8d4239f2f..492fe6aa32 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/HeadersDsl.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/HeadersDsl.kt @@ -438,17 +438,13 @@ open class HeadersDsl: CommonDsl() { val TEXT_XML = MediaTypes.TEXT_XML /** - * Adds and configures a configurer. + * Adds a header. * - * @param configurer The lambda to configure the configurer. + * @param name The name of the header. + * @param value The value of the header. */ - fun header(configurer: HeaderDsl.() -> Unit) { - try { - val header = HeaderDsl().apply(configurer) - this.headers[header.name] = header.value - } catch (ex: IllegalStateException) { - throw IllegalStateException("Header is missing its name or value") - } + fun header(name: String, value: Any) { + this.headers[name] = value } internal fun get(): Headers { diff --git a/specs/spring-cloud-contract-spec-kotlin/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt b/specs/spring-cloud-contract-spec-kotlin/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt index 2e066fe9da..3d9b657c58 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt @@ -39,20 +39,14 @@ class ContractTests { url = url("/foo") method = PUT headers { - header { - name = "foo" - value = "bar" - } + header("foo", "bar") } body = body("foo" to "bar") } response { status = OK headers { - header { - name = "foo2" - value = "bar" - } + header("foo2", "bar") } body = body("foo2" to "bar") } @@ -148,20 +142,14 @@ class ContractTests { messageFrom = messageFrom("input") messageBody = messageBody("foo" to "bar") headers { - header { - name = "foo" - value = "bar" - } + header("foo", "bar") } } outputMessage { sentTo = sentTo("output") body = body("foo2" to "bar") headers { - header { - name = "foo2" - value = "bar" - } + header("foo2", "bar") } } } @@ -200,20 +188,14 @@ class ContractTests { messageFrom("input") messageBody("foo" to anyNonBlankString()) headers { - header { - name = "foo" - value = anyNumber() - } + header("foo", anyNumber()) } } outputMessage { sentTo("output") body("foo2" to anyNonEmptyString()) headers { - header { - name = "foo2" - value = anyIpAddress() - } + header("foo2", anyIpAddress()) } } } @@ -415,20 +397,18 @@ then: method = GET url = url("/path") headers { - header { - name = "Accept" + header(name = "Accept", value = value( consumer(regex("text/.*")), producer("text/plain") ) - } - header { - name = "X-Custom-Header" + ) + header(name = "X-Custom-Header", value = value( consumer(regex("^.*2134.*$")), producer("121345") ) - } + ) } } response { @@ -439,10 +419,7 @@ then: "created" to "2014-02-02 12:23:43" ) headers { - header { - name = "Content-Type" - value = "text/plain" - } + header("Content-Type", "text/plain") } } } @@ -451,20 +428,18 @@ then: method = GET url = url("/path") headers { - header { - name = "Accept" + header(name = "Accept", value = value( consumer(regex("text/.*")), producer("text/plain") ) - } - header { - name = "X-Custom-Header" + ) + header(name = "X-Custom-Header", value = value( consumer(regex("^.*2134.*$")), producer("121345") ) - } + ) } } response { @@ -475,10 +450,7 @@ then: "created" to "2014-02-02 12:23:43" ) headers { - header { - name = "Content-Type" - value = "text/plain" - } + header("Content-Type", "text/plain") } } } @@ -533,10 +505,7 @@ then: url = url("/path") body = body("id" to mapOf("value" to "132")) bodyMatchers { - jsonPath { - path = "$.id.value" - matcher = byRegex(anInteger()) - } + jsonPath( "$.id.value", byRegex(anInteger())) } } response { @@ -550,10 +519,7 @@ then: contentType = APPLICATION_JSON } bodyMatchers { - jsonPath { - path = "$.id.value" - matcher = byTimestamp() - } + jsonPath("$.id.value", byTimestamp()) } } } @@ -581,84 +547,6 @@ then: } } - @Test - fun `should throw error when body matcher is not configured correctly`() { - assertThrows { - contract { - request { - method = GET - url = url("/cookie") - bodyMatchers { - jsonPath { - matcher = byRegex(anInteger()) - } - } - } - response { - status = OK - } - } - }.also { - assertThat(it.message).contains("Body matcher is missing its path or matcher") - } - - assertThrows { - contract { - request { - method = GET - url = url("/cookie") - bodyMatchers { - jsonPath { - path = "$.id.value" - } - } - } - response { - status = OK - } - } - }.also { - assertThat(it.message).contains("Body matcher is missing its path or matcher") - } - assertThrows { - contract { - request { - method = GET - url = url("/cookie") - bodyMatchers { - xPath { - matcher = byRegex(anInteger()) - } - } - } - response { - status = OK - } - } - }.also { - assertThat(it.message).contains("Body matcher is missing its path or matcher") - } - - assertThrows { - contract { - request { - method = GET - url = url("/cookie") - bodyMatchers { - xPath { - path = "$.id.value" - } - } - } - response { - status = OK - } - } - }.also { - assertThat(it.message).contains("Body matcher is missing its path or matcher") - } - } - @Test fun `should support query parameters for url`() { val contract = contract { @@ -752,47 +640,6 @@ then: } } - @Test - fun `should throw error when header is not configured correctly`() { - assertThrows { - contract { - request { - method = GET - url = url("/cookie") - headers { - header { - name = "foo" - } - } - } - response { - status = OK - } - } - }.also { - assertThat(it.message).contains("Header is missing its name or value") - } - - assertThrows { - contract { - request { - method = GET - url = url("/cookie") - headers { - header { - value = "bar" - } - } - } - response { - status = OK - } - } - }.also { - assertThat(it.message).contains("Header is missing its name or value") - } - } - @Test fun `should work with cookies`() { val contract = contract { @@ -800,27 +647,15 @@ then: method = GET url = url("/cookie") cookies { - cookie { - name = "name" - value = "foo" - } - cookie { - name = "name2" - value = "bar" - } + cookie("name", "foo") + cookie("name2", "bar") } } response { status = OK cookies { - cookie { - name = "name" - value = "foo" - } - cookie { - name = "name2" - value = "bar" - } + cookie("name", "foo") + cookie("name2", "bar") } } } @@ -840,47 +675,6 @@ then: } } - @Test - fun `should throw error when cookie is not configured correctly`() { - assertThrows { - contract { - request { - method = GET - url = url("/cookie") - cookies { - cookie { - value = "bar" - } - } - } - response { - status = OK - } - } - }.also { - assertThat(it.message).contains("Cookie is missing its name or value") - } - - assertThrows { - contract { - request { - method = GET - url = url("/cookie") - cookies { - cookie { - name = "foo" - } - } - } - response { - status = OK - } - } - }.also { - assertThat(it.message).contains("Cookie is missing its name or value") - } - } - @Test fun `should support fromRequest`() { val contract = contract {