Sometimes we want more than just a simple stub from wiremock, sometimes we want to create a scenario. We want Wiremock to do something different when we call it a second or third time. A common scenario is a request that first fails, but on second try is OK. A use case for this is that every connection will transiently fail at some point and Wiremock can be used to test this scenario.
Below I have created a scenario that first returns a HTTP 500 status code, then a 404 status code and at the end a 200 status code.
//Setup first request to return 500
server
.Given(
Request.Create()
.WithPath("/weatherforecastbackend")
.UsingGet()
)
.InScenario("my-scenario")
.WillSetStateTo("my-scenario-step2")
.RespondWith(
Response.Create()
.WithStatusCode(500)
.WithBody("wiremock: this is a 500!")
);
//Setup second request to return 404
server
.Given(
Request.Create()
.WithPath("/weatherforecastbackend")
.UsingGet()
)
.InScenario("my-scenario")
.WhenStateIs("my-scenario-step2")
.WillSetStateTo("my-scenario-step3")
.RespondWith(
Response.Create()
.WithStatusCode(404)
.WithBody("wiremock: this is a 404!")
);
//Setup third request to return 200
server
.Given(
Request.Create()
.WithPath("/weatherforecastbackend")
.UsingGet()
)
.InScenario("my-scenario")
.WhenStateIs("my-scenario-step3")
.RespondWith(
Response.Create()
.WithStatusCode(200)
.WithBody("This is a body")
);
Note that in the above I always return a body, this is to tell myself that this is wiremock responding, so I do not get the 404 mixed up with a regular 404 when debugging :)
For scenarios in Wiremock you need to set each request matcher to belong to a given scenario, for example: .InScenario("my-scenario")
. You can then set which State in the scenario this request matcher belongs to, for example: .WhenStateIs("my-scenario-step2")
. Lastly, you can set which state you wish to transition to once the current state is triggered, for example: .WillSetStateTo("my-scenario-step3")
.
We can test the above with a simple unit test:
var httpClient = new HttpClient();
var firstRequest = await httpClient.GetAsync(
"http://localhost:58116/weatherforecastbackend");
Assert.Equal(HttpStatusCode.InternalServerError, firstRequest.StatusCode);
var secondRequest = await httpClient.GetAsync(
"http://localhost:58116/weatherforecastbackend");
Assert.Equal(HttpStatusCode.NotFound, secondRequest.StatusCode);
var thirdRequest = await httpClient.GetAsync(
"http://localhost:58116/weatherforecastbackend");
Assert.Equal(HttpStatusCode.OK, thirdRequest.StatusCode);
Assert.Equal("This is a body", await thirdRequest.Content.ReadAsStringAsync());
The result of this can be seen in the below image:
That is basically all there is to it, I hope you enjoyed this post, let me know in the comments what you think! :)