Closed pfrank13 closed 7 years ago
Here's how pact-jvm handles this issue:
@TargetRequestFilter
public void exampleRequestFilter(HttpRequest request) {
request.addHeader("Authorization", "OAUTH hdsagasjhgdjashgdah...");
}
The user provides a method annotated with @TargetRequestFilter
, then that method is applied to every incoming request.
I want to reuse the http://wiremock.org/docs/response-templating/ Response templating approach. You'd be able to set sth like this:
Contract contractDsl = Contract.make {
request {
method 'GET'
url '/api/v1/xxxx'
headers {
header(authorization(), "secret")
}
body(foo: "bar")
}
response {
status 200
headers {
header(authorization(), fromRequest().headers(authorization()))
}
body(
url: fromRequest().url(),
headers: fromRequest().headers(authorization())
)
}
}
I'm still prototyping the API . Cause @pfrank13 I understand that this is the problem? That you'd like to set in the response of the header the Authorization header ? Cause if this relates to the server tests and that you'd like to set some headers than you can use this (I think you can use this)
RestAssuredMockMvc.postProcessors().add(new RequestPostProcessor() {
@Override
MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
// add the headers
return request
}
})
or you can add your own custom filter and do sth similar as presented above and add it to mock mvc context.
My issue is all about the client side, so specifically the retrieval of the auth token being strictly before testing a given endpoint and setting it in the request, that's it. The additional curveball is the auth token may come from another host.
But you don't need a real token. Why not just test the integration via some fixed headers? Can you show how your client test looks like?
In my particular case I'm not in control of the server side API, so I'm only really using half of Cloud Contract. I'm POCing using Spring Cloud Contract to detect contract drift with our 3rd parties, it's a problem that we have with our integrations. So the token call needs to happen because I'm using a live API.
This is what I'm doing
Contract.make {
request {
method 'POST'
urlPath '/v1/tokens'
body ([name: 'example@example.com',
nameType: 'EMAIL',
credential: 'credential2',
credentialType: 'CREDENTIAL']
)
headers {
accept(applicationJson())
contentType(applicationJson())
header('Authorization', 'Basic someBasicAuth=')
}
}
response {
status 200
body (
[access_token:'123']
)
headers {
contentType(applicationJson())
}
testMatchers {
jsonPath('$.access_token', byCommand('saveAuthToken($it)'))
}
}
}
Contract.make {
request {
method 'GET'
urlPath '/v2/menus/1000/places/1234'
headers {
accept(applicationJson())
contentType(applicationJson())
header('Authorization', 'Basic someBasicAuth=')
header('Authorization', execute('authToken()'))
}
}
...
}
I don't follow. This contract is for the consumer side (since you can't control the producer side) ? Or is that a contract that simulates the producer side?
Are you using contracts to perform some end to end tests? Or are you trying to use SC-Contract's DSL to defne the API of the 3rd party?
Yeah that contract is all the consumer side, I'm using the DSL to just detect drift, e.g. when the 3rd party breaks what they were previously doing. I'm using the maven plugin in explicit mode. But more abstractly having to get an auth token to hit other endpoints is a fairly common thing to have to do, so even if I was controlling the server I would presumably still have the same issue as a client, i.e. I would need to get a real token in order to hit other endpoints during a test.
Hmm ok so the DSL works as a scenario for your tests. Fair enough, you're not the first person who does it like this ;) I think the best thing to do would be to use the post processor
RestAssuredMockMvc.postProcessors().add(new RequestPostProcessor() {
@Override
MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
// add the headers
return request
}
})
In DSL I'd put a sample value for the Authorization
header but in the post processor I would do a real call to fetch the real header value and I'd amend the request to contain that value of the header. In the response for the producer side I'd check if the authorization header is present and matches some regex - I wouldn't check a concrete value. For the stub I'd put a fixed value of the header and that's it. Does it make sense?
Yeah that makes sense, although in my particular case I'm using RestAssured and not RestAssuredMockMvc, I don't think RestAssured has post processors, at least as far as I know.
You can call RestAssured.authentication
- look here - https://github.com/rest-assured/rest-assured/wiki/usage#default-values .
So actually I think we can close this issue cause there's nothing programatic to be done here right?
Yeah looks that way. Thanks for the help!
Currently there is no facility for supporting auth tokens that are needed to be obtained before other endpoints can be hit against a given API. This seems like something that is very common that would be useful to have top level support for in the project.
To me there are 2 large issues
Currently I have a hack that, for the most part, conquers the second item in an extreme code smelly way for the non 3 legged oauth case. Hitting the token generating endpoint in my API I extract the token and then save that out in a static member in the Base class by adding an instance method that is executed via
then subsequent endpoint tests retrieve that value via
I use the scenario ordering facility to make sure the token retrieval happens first, which slaps on
Obviously this approach is a hack and totally breaks down for people that need multiple different base classes, that's forgetting the smell of an instance member setting a static member.