javaspringgroovyspring-cloud-contract

Spring Cloud Contract - Re-use path variable in request for repsonse


I'm currently trying to build a contract like this:

Contract.make {
    description("""
Represents a successful scenario of getting an account
```
given:
    account id
when:
    api request for an account
then:
    return account
```
""")
    request {
        method 'GET'
        urlPath(regex("/api/v1/account/" + anyNumber()))
    }
    response {
        status 200
        body(
                accountNumber: value(anyNumber())
        )
        headers {
            contentType(applicationJson())
        }
    }
}

But getting an exception

cloud:spring-cloud-contract-maven-plugin:4.0.0:generateTests failed: java.util.regex.PatternSyntaxException: Illegal repetition near index 34
[ERROR] /api/v1/account/ClientDslProperty{
[ERROR] clientValue=-?(\d*\.\d+|\d+), 
[ERROR]         serverValue=-90366052}
[ERROR]                                   ^

If reading the documentation here this should be possible.

If I use hardcoded values it works e.g.

Contract.make {
    description("""
Represents a successful scenario of getting an account
```
given:
    account id
when:
    api request for an account
then:
    return account
```
""")
    request {
        method 'GET'
        url '/api/v1/account/1234'
    }
    response {
        status 200
        body("""
            {
                "accountNumber": "${value(1234)}"
            }
            """)
        headers {
            contentType(applicationJson())
        }
    }
}

Can someome help me out please? Thanks a lot in advance


Solution

  • Spring Cloud Contract is new to me, but reading the documentation (https://cloud.spring.io/spring-cloud-contract/reference/html/project-features.html#contract-dsl-regex) suggests that when you define the request with a regex, you should be specifying that it's for the consumer side. Also, anyNumber() doesn't return a simple string that can be concatenated into a regex pattern like you've done. I think you want something like this:

    url value(consumer(regex('/api/v1/account/\d+')))
    

    Then, to reference the number in your response section, you probably want something like:

    body(
        accountNumber: fromRequest().path(3)
    )
    

    (this is from the section of documentation that you linked to in your question)