I would like to unit test the next method:
public static async Task SetResponseBody(HttpResponse response, string message)
{
var originalResponseBody = response.Body;
var responseBody = new MemoryStream();
response.Body = responseBody;
response.ContentType = "application/json";
dynamic body = new { Message = message };
string json = JsonSerializer.Serialize(body);
await response.WriteAsync(json);
response.Body.Seek(0, SeekOrigin.Begin);
await responseBody.CopyToAsync(originalResponseBody);
}
The last two lines are used from this post.
The current unit test implementation is:
[TestMethod]
public async Task SetResponseBody_TestMessageAsync()
{
var expected = "TestMessage";
string actual = null;
var responseMock = new Mock<HttpResponse>();
responseMock
.Setup(_ => _.Body.WriteAsync(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<CancellationToken>()))
.Callback((byte[] data, int offset, int length, CancellationToken token) =>
{
if (length > 0)
actual = Encoding.UTF8.GetString(data);
})
.Returns(Task.CompletedTask);
await ResponseRewriter.SetResponseBody(responseMock.Object, expected);
}
The unit tests fails due to a NullReferenceException which is raised once the test hits the 'await response.WriteAsync(json);
' line of code. Could you point me in the right direction in order to fix this exception, so the test will pass?
Summarized: The unit tests needs to check if the given 'TestMessage' is actually written to the Body of the response.
Background information:
I'm calling the SetResponseBody
method in order to modify the response body as soon as the 'OnRedirectToIdentityProvider
' event is raised from AddOpenIdConnect
.
OnRedirectToIdentityProvider = async e =>
{
// e is of type RedirectContext
if (e.Request.Path.StartsWithSegments("/api")))
{
if (e.Response.StatusCode == (int)HttpStatusCode.OK)
{
e.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
// TestMessage is a const
// e.Response is readonly (get) so it's not possible to set it directly.
await ResponseRewriter.SetResponseBody(e.Response, TestMessage);
}
e.HandleResponse();
}
await Task.CompletedTask;
}
.NET Core 3.1, WebApi, OpenId
There are too many internals that need to be configured for the abstract HttpResponse
to work as intended when mocking it.
I would suggest using DefaultHttpContext
and extracting the default response created within that context.
[TestMethod]
public async Task SetResponseBody_TestMessageAsync() {
//Arrange
string expected = "TestMessage";
string actual = null;
HttpContext httpContext = new DefaultHttpContext();
HttpResponse response = httpContext.Response
//Act
await ResponseRewriter.SetResponseBody(response, expected);
//Assert
//...
}
for the assertion, extract the content of the response body and assert its expected behavior.