Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing .Net CORE 2.0 WebAPI - Mock (MOQ) HTTP POST with text stream body (not model)

I am trying to unit test my HTTP POST method of my .Net CORE 2.0 API Controller which stream-reads data... Cannot use a "model" type approach as the incoming stream raw data.

Here is the basics of the controller method.

[HttpPost()]
[Authorize(Roles = "contributor")]
public async Task<IActionResult> SubmitReport()
{
    IActionResult result = null;
    _logger.LogInformation("POST Request");

    var buffer = new byte[this.Request.ContentLength.Value];

    await this.Request.Body.ReadAsync(buffer, 0, buffer.Length);
    string content = System.Text.Encoding.UTF8.GetString(buffer);

    // Do something with the 'content'

    return (Accepted());  // Assuming all was OK
}

And here's my Unit Test... or rather as far as I can get..

[TestMethod]
public void eFormController_SubmitReport_MockService_ExpectHttpStatusAccepted()
{
    var mockContextAccessor = new Mock<IHttpContextAccessor>();
    var context = new DefaultHttpContext();
    mockContextAccessor.Setup(x => x.HttpContext).Returns(context);

    var mockLogger = new Mock<ILogger<object>>();
    var ctrl = new Controllers.eFormsController();

    var result = ctrl.SubmitReport();

    Assert.IsInstanceOfType(result, typeof(Microsoft.AspNetCore.Mvc.AcceptedResult));
}

When I run the test as it stands, the this.Request property is null so how do I Mock a proper HTTP POST request.

Google has yet to yield any favourable results as they all assume a fully defined model, and not a text stream

like image 422
Chris Hammond Avatar asked Oct 23 '18 12:10

Chris Hammond


People also ask

Why do we use Moq in unit testing?

It is used in unit testing to isolate your class under test from its dependencies and ensure that the proper methods on the dependent objects are being called.


1 Answers

You have already done most of the work by using the DefaultHttpContext.

Arrange a request that has a body (stream) and the necessary properties to allow the method under test to flow as expected.

Should be able to exercise the test from there

[TestMethod]
public async Task eFormController_SubmitReport_MockService_ExpectHttpStatusAccepted() {
    //Arrange
    var data = "Hello World!!";
    var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(data));

    var httpContext = new DefaultHttpContext();
    httpContext.Request.Body = stream;
    httpContext.Request.ContentLength = stream.Length;

    var mockLogger = new Mock<ILogger<object>>();

    var controllerContext = new ControllerContext() {
        HttpContext = httpContext,
    };

    var controller = new Controllers.eFormsController(mockLogger.Object) {
         ControllerContext = controllerContext,
    };

    //Act
    var result = await controller.SubmitReport();

    //Assert
    Assert.IsInstanceOfType(result, typeof(Microsoft.AspNetCore.Mvc.AcceptedResult));
}
like image 93
Nkosi Avatar answered Oct 04 '22 01:10

Nkosi