cjstehno / ersatz

🤖 A simulated HTTP server for testing client code with configurable responses.
https://cjstehno.github.io/ersatz
Apache License 2.0
47 stars 5 forks source link

Multiple value headers not matching #65

Closed pmack24 closed 7 years ago

pmack24 commented 7 years ago

It seems that request with multiple value headers are not matched. Below is the expectation.

server.expectations {
    get('/api/hello') {
        called 1
        header 'Accept', 'application/json'
        header 'Accept', 'application/vnd.company+json'
        responder {
            code 200
                content  'msg': 'World', 'application/vnd.company+json'
            }
        }
}

However, this does not seem to match. Looking at the code it appears that only the first value is compared:

static RequestMatcher header(final String name, final Matcher<String> m) {
    new RequestMatcher(m, { ClientRequest cr -> cr.headers.getFirst(name) })
}
public String getFirst(String headerName) {
    HeaderValues headerValues = getEntry(headerName);
    if (headerValues == null) return null;
    return headerValues.getFirst();
}

Can this be fixed, or would you prefer I send a PR ?

Thanks

cjstehno commented 7 years ago

Erg, GitHub didn't send me an email about this. I will look into this in the next few days.

cjstehno commented 7 years ago

I am currently working on this issue, but if you can't wait a few days a workaround is to define a matcher in the expectation:

header 'Accept', Matchers.isOneOf('application/json', 'application/vnd.company+json')

A test would look something like this:

def 'multiple header matching support'() {
    setup:
    ersatzServer.expectations {
        get('/api/hello') {
            called 1
//                header 'Accept', 'application/json'
//                header 'Accept', 'application/vnd.company+json'
            header 'Accept', Matchers.isOneOf('application/json', 'application/vnd.company+json')
            responder {
                code 200
                content 'msg': 'World', 'application/vnd.company+json'
            }
        }
    }

    when:
    okhttp3.Response response = client.newCall(new okhttp3.Request.Builder().get().url(url('/api/hello'))
//            .header('Accept', 'application/json')
        .header('Accept', 'application/vnd.company+json')
        .build()
    ).execute()

    then:
    response.code() == 200
    response.body().string() == '[msg:World]'

    and:
    ersatzServer.verify()
}

At this point I also see this as how you would implement the case where your request will match at least one of the specified header. In your example above, the request would have to have ALL of the specified header values.

I will probably also provide other convenience methods for specifying more than one header value.

cjstehno commented 7 years ago

There is a fix for this in the development branch (1.5.0 release coming soon) - I will close the issue for now, but feel free to reopen it if you run into issues.