I'm doing (learning about) integration testing on my web api. One of my web api methods calls out to EXTERNAL web service that takes Basic
authorization.
So, I've intercepted my external web api call via WireMock with the following code in my WebApplicationFactory<>
class:
services.AddHttpClient(
$"ExternalApiClient",
httpClient =>
{
httpClient.BaseAddress = new Uri( wireMockServer.Url );
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String( Encoding.UTF8.GetBytes( "secret" ) )
);
httpClient.DefaultRequestHeaders.Add( "Accept", "*/*" );
}
);
With this, when I test my endpoint which requests its own HttpClient
for the external service, it uses the WireMock server and serves up 'known' requests:
using var httpClient = httpClientFactory.CreateClient( "ExternalApiClient" );
So I would like to write two tests:
Basic
authentication password is wrong.I can't think of a clean way to do this. Is there a WireMock (or integration test strategy) that would allow for this? I've written a WireMock pattern matcher to successfully do this, but I have to manually run one test or the other based on whether I've put the right password in my AddHttpClient
call (I can't run all tests within the project with my solution).
My solution was as follows (if better options, please let me know):
Since the credential 'management' is inside the API that WireMock is replacing, I didn't really see a way to simulate a 'real scenario' where simply the credentials were wrong. But all I really want to test is that my Api handles this error gracefully and returns expected result (a Api-Authorization-Failed
header in the response).
So I just introduced a fake url that WireMock would intercept and return 'invalid credential response' but in reality, the callers of my web api would never pass this url.
server.Given(
Request.Create()
.WithPath( "/integration/unauthorized_api" )
.UsingGet()
).RespondWith(
Response.Create()
.WithBody( @"{
""timestamp"": 1676572342225,
""status"": 401,
""error"": ""Unauthorized"",
""path"": ""{{request.path}}""
}" )
.WithHeader( "content-type", "application/json; charset=utf-8" )
.WithStatusCode( HttpStatusCode.OK )
);
Then my [Fact]
looks like this:
[Fact]
public async Task Get_ReturnsUnauthorized_WhenNexgenApiCredentialsAreWrong()
{
// Arrange
var payload = GetValidRequest( "/integration/unauthorized_api", null );
// Act
var response = await httpClient.PostAsJsonAsync( "/nexgen", payload );
// Assert
response.StatusCode.Should().Be( HttpStatusCode.Unauthorized );
response.Headers.Single( h => h.Key == "Api-Authorization-Failed" ).Value.First().Should().Be( "true" );
}