Codearte / accurest

Accurest - Consumer Driven Contracts verifier for Java. Moved to:
https://github.com/spring-cloud/spring-cloud-contract
Apache License 2.0
99 stars 23 forks source link

Dsl 'regex()' not wrapped by closure in response body produces '{cursor:2}' in stub #202

Closed yu55 closed 8 years ago

yu55 commented 8 years ago

Following test fails:

def 'should generate response stub with regex inside closure and with regex without closure'() {
    given:
        GroovyDsl groovyDsl = GroovyDsl.make {
            request {}
            response {
                status 200
                body(
                        amount: value(
                                client(
                                        { regex('[0-9.]+') }
                                ),
                                server(
                                        '100.00'
                                )
                        ),
                        applicationName: value(
                                client(
                                        regex('.*')
                                ),
                                server(
                                        'Acme'
                                )
                        )
                )
            }
        }
    when:
        def wireMockStub = toWireMockClientJsonStub(groovyDsl)
    then:
        AssertionUtil.assertThatJsonsAreEqual(('''
            {
                "request" : { },
                "response" : {
                "status" : 200,
                "body" : "{\\"amount\\":{\\"regex\\":\\"[0-9.]+\\"},\\"applicationName\\":{\\"regex\\":\\".*\\"}}"
            }
        }'''), wireMockStub)
    and:
        stubMappingIsValidWireMockStub(wireMockStub)
}

with error:

java.lang.AssertionError: response.body
Expected: {"amount":{"regex":"[0-9.]+"},"applicationName":{"regex":".*"}}
     got: {"amount":{"regex":"[0-9.]+"},"applicationName":{"cursor":2}}

    at org.skyscreamer.jsonassert.JSONAssert.assertEquals(JSONAssert.java:222)
    at org.skyscreamer.jsonassert.JSONAssert.assertEquals(JSONAssert.java:192)
    at io.codearte.accurest.util.AssertionUtil.assertThatJsonsAreEqual(AssertionUtil.groovy:10)
    at io.codearte.accurest.dsl.WireMockGroovyDslSpec.should generate response stub with regex inside closure and with regex without closure(WireMockGroovyDslSpec.groovy:1480)

This {"cursor":2} happens for a regex pattern not wrapped by closure. Map that represents response body contains java.util.regex.Pattern, which then groovy.json.JsonOutput.writeObject() method tries to serialize, which unfortunately produces {\"cursor\":2} text. Groovy doesn't know how to properly serialize java.util.regex.Pattern into JSON - there is no separate else if for java.util.regex.Pattern in groovy.json.JsonOutput.writeObject() method like there is for Closure.class (which produces proper output string).

marcingrzejszczak commented 8 years ago

Hmm this looks like a regression. There should be no closure there. We have some hacks to store info in json that a value is a regex. I'll check it out

marcingrzejszczak commented 8 years ago

Hmm why do you want to have regular expression in response?

The Wiremock JSON can't have regular expressions in the response cause it doesn't make much sense. You want the receiver to get a strictly defined value.

You're getting this cursor thing cause it's doing a toString() on the Pattern which shouldn't be there in the response side. We could throw exceptions during Wiremock JSON generation for that matter.

@jkubrynski - WDYT?

yu55 commented 8 years ago

But why do you have regex in closure in the first place?

Didn't know that it's not suppose to sit inside closure. E.g. in should convert groovy dsl stub to wireMock stub for the client side test it is inside a closure in response body. Do we have some kind of specification what is legal and what is not with GroovyDsl?

The Wiremock JSON can't have regular expressions in the response cause it doesn't make much sense. You want the receiver to get a strictly defined value.

You're right. I forgot about that. I think what I wanted to do lately when working with accurest was actually: value(regex(.*)) instead of putting regex() inside client/server, and when checking stubs this "cursor:2" looked wrong. I wanted to have this regex on server side tests, but yeah, it doesn't make sense in client response... Sorry, I got confused... Also looking on this test should convert groovy dsl stub to wireMock stub for the client side convinced me that regex in closure makes sense.

marcingrzejszczak commented 8 years ago

Didn't know that it's not suppose to sit inside closure. E.g. in should convert groovy dsl stub to wireMock stub for the client side test it is inside a closure in response body. Do we have some kind of specification what is legal and what is not with GroovyDsl?

I mean you can pass whatever you want there... It's just unnecessary cause you can pass directly the value of regex

You're right. I forgot about that.

No problem - it's good that we found the solution

I think what I wanted to do lately when working with accurest was actually: value(regex(.*))

You can do that but it will be wrong cause the response side won't have a concrete value.

Sorry, I got confused... Also looking on this test should convert groovy dsl stub to wireMock stub for the client side convinced me that regex in closure makes sense.

We have to change the test then cause it's missleading

marcingrzejszczak commented 8 years ago

The test is fixed: https://github.com/Codearte/accurest/commit/f3221f51b3838f3aa614c22ba4cd53b4adb033a3