×

iFour Logo

Unit testing a custom middleware in ASP.NET Core with Interface

Kapil Panchal - October 21, 2020

Listening is fun too.

Straighten your back and cherish with coffee - PLAY !

  • play
  • pause
  • pause
Unit testing a custom middleware in ASP.NET Core with Interface

What is unit test?


A unit test is a type of testing.It is the Small Part of code that can be logically in a Program and test that code is work properly that is testing.

The latest versions of unit testing can be found in frameworks like JUnit, or testing tools like Test Complete. You will also find SUnit, which is the mother of all unit testing frameworks it is created by Kent Back.

How does the tests look like?


A unit can be almost anything you want it is, a line of code or a method, and a class. Smaller tests give you a more detail view of how your code is performing. There is also the practical aspect that when you test very small units, your tests can be run fast; like so many tests in a second fast.

Consider this sample code

 
def divider (x, y)
return x/y
End
		   

This example is simple, but it gives you an idea of what I mean by small. Small tests also have the benefit of building it harder to cross-systems from code into a database, or 3rd party system. There is not anything wrong with crossing systems, but there is a result like gradually slowing your tests, a test suite that takes hours to run.

What is Middleware?


Middleware’s are a fundamental part of an ASP.NET application, introduced from day one. They are executed in the order they are added on every request and could be considered similar to the HTTP Handlers and HTTP Modules of the classic ASP.NET. Since middleware’s can execute code before or after calling subsequent within the pipeline, they're considered ideal for plenty of varied application features, including exception handling, logging, authentication, etc.

Middleware is often tested in isolation with Test Server. It allows you to instantiate an app pipeline containing only the components that you simply got to test.

Advantages of Middleware


  • Requests are sent in-memory instead of being serialized over the network.
  • Exceptions within the middleware can flow directly back to the calling test.
  • It's possible to customize server data structures, like HttpContext, directly within the test.

Middleware’s offer a more powerful and flexible solution and for that, they need to be tested! Thankfully there's how to try to that so let's first see what we are getting to test then just get in there to Example:

You can need to Install Microsoft.AspNetCore.Testhst

First of All, you can need to Configure the processing pipeline to use the middleware for the test. part of program configure Processing pipeline is shown below.

 
[Fact]
public async Task MiddlewareTest_ReturnsNotFoundForRequest()
 {
using varhst = await new hstBuilder().ConfigureWebhst(webBuilder =>
 {
webBuilder.UseTestServer().ConfigureServices(services =>
 {
services.AddMyServices();
 })
.Configure(app =>
 {
app.UseMiddleware();
  });
  })
.StartAsync();
}

After that you need to send requests with the HttpClient sample code is below.


[Fact]
 public async Task MiddlewareTest_ReturnsNotFoundForRequest()
 {
using varhst = await new hstBuilder().ConfigureWebhst(webBuilder =>
 {
webBuilder.UseTestServer().ConfigureServices(services =>
 {
services.AddMyServices();
 })
.Configure(app =>
 {
app.UseMiddleware();
 });
 })
.StartAsync();
var response = await hst.GetTestClient().GetAsync("/");
}

Assert the result and make an assertion of the opposite of the result that you expect. An embryonic run with a false positive assertion confirms that the test fails. when the middleware is performing Truly. Start test and confirm that the test is failed.

In this example, the middleware returns a 404-status code which is NOT FOUND code when the root endpoint is requested. Make the first one test run with Assert.NotEqual (); which should be fail.

 
[Fact]
public async Task MiddlewareTest_ReturnsNotFoundForRequest()
 {
using varhst = await new hstBuilder().ConfigureWebhst(webBuilder =>
 {
webBuilder.UseTestServer().ConfigureServices(services =>
 {
services.AddMyServices();
 })
.Configure(app =>
 {
app.UseMiddleware();
 });
 })
.StartAsync();
var response = await hst.GetTestClient().GetAsync("/");
Assert.NotEqual(HttpStatusCode.NotFound, response.StatusCode);
 }

Change the assertion for test the middleware under normal operating ambiance. The final test uses Assert.Equal( );. Run the test a second time to confirm that it was successful.

 
[Fact]
public async Task MiddlewareTest_ReturnsNotFoundForRequest()
  {
using varhst = await new hstBuilder()
.ConfigureWebhst(webBuilder =>
  {
webBuilder.UseTestServer().ConfigureServices(services =>
  {
services.AddMyServices();
  })
.Configure(app =>
  {
app.UseMiddleware();
  });
  })
.StartAsync();
var response = await hst.GetTestClient().GetAsync("/");
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}

Looking to Hire Dedicated .ASP.Net Core Developer ? Contact Now.

Send requests with HttpContext


A test app is also sending a request using SendAsync(Action, CancellationToken). In this example, several checks are made when https:// example. com/A/Path/?and=query is done by the middleware.

 
[Fact]
public async Task TestMiddleware_ExpectedResponse()
 {
using varhst = await new hstBuilder()
.ConfigureWebhst(webBuilder =>
 {
webBuilder.UseTestServer().ConfigureServices(services =>
 {
services.AddMyServices();
 })
.Configure(app =>
 {
app.UseMiddleware();
 });
 })
.StartAsync();
var server = hst.GetTestServer();
server.BaseAddress = new Uri("https://example.com/A/Path/");
var context = await server.SendAsync(c =>
 {
c.Request.Method = HttpMethods.Post;
c.Request.Path = "/and/file.txt";
c.Request.QueryString = new QueryString("?and=query");
 });
Assert.True(context.RequestAborted.CanBeCanceled);
Assert.Equal(HttpProtocol.Http11, context.Request.Protocol);
Assert.Equal("POST", context.Request.Method);
Assert.Equal("https", context.Request.Scheme);
Assert.Equal("example.com", context.Request.hst.Value);
Assert.Equal("/A/Path", context.Request.PathBase.Value);
Assert.Equal("/and/file.txt", context.Request.Path.Value);
Assert.Equal("?and=query", context.Request.QueryString.Value);
Assert.NotNull(context.Request.Body);
Assert.NotNull(context.Request.Headers);
Assert.NotNull(context.Response.Headers);
Assert.NotNull(context.Response.Body);
Assert.Equal(404, context.Response.StatusCode);
Assert.Null(context.Features.Get().ReasonPhrase);
 }

SendAsync allow the direct configuration of an HttpContext object instead of using the HttpClient abstractions. Use SendAsync to control structures only available on the server, like HttpContext.Items or HttpContext.Features.

As with the Previous example that tested for a 404 - Not Found response, check the other for every assert statement within the preceding test. The check confirms that the test fails correctly when the middleware is working normally. After you've confirmed that the false-positive test works, set the ultimate assert statements for the expected conditions and values of the test. Run it again to verify that the test passes.

Conclusion


Using Middleware unit testing you can test parts of code which is placed in program. You can also get more detail result of your testing. Using these you can customize data structures, like HttpContext, directly within the test. You can test from both sides correct or wrong.We hope this blog will be helpful for you to understand concept of unit testing a custom middleware in ASP.NET Core.

Unit testing a custom middleware in ASP.NET Core with Interface What is unit test? A unit test is a type of testing.It is the Small Part of code that can be logically in a Program and test that code is work properly that is testing. The latest versions of unit testing can be found in frameworks like JUnit, or testing tools like Test Complete. You will also find SUnit, which is the mother of all unit testing frameworks it is created by Kent Back. How does the tests look like? A unit can be almost anything you want it is, a line of code or a method, and a class. Smaller tests give you a more detail view of how your code is performing. There is also the practical aspect that when you test very small units, your tests can be run fast; like so many tests in a second fast. Consider this sample code   def divider (x, y) return x/y End This example is simple, but it gives you an idea of what I mean by small. Small tests also have the benefit of building it harder to cross-systems from code into a database, or 3rd party system. There is not anything wrong with crossing systems, but there is a result like gradually slowing your tests, a test suite that takes hours to run. What is Middleware? Middleware’s are a fundamental part of an ASP.NET application, introduced from day one. They are executed in the order they are added on every request and could be considered similar to the HTTP Handlers and HTTP Modules of the classic ASP.NET. Since middleware’s can execute code before or after calling subsequent within the pipeline, they're considered ideal for plenty of varied application features, including exception handling, logging, authentication, etc. Read More: Ultimate Guide For Implementing Repository Pattern And Unit Of Work For .net Core Middleware is often tested in isolation with Test Server. It allows you to instantiate an app pipeline containing only the components that you simply got to test. Advantages of Middleware Requests are sent in-memory instead of being serialized over the network. Exceptions within the middleware can flow directly back to the calling test. It's possible to customize server data structures, like HttpContext, directly within the test. Middleware’s offer a more powerful and flexible solution and for that, they need to be tested! Thankfully there's how to try to that so let's first see what we are getting to test then just get in there to Example: You can need to Install Microsoft.AspNetCore.Testhst First of All, you can need to Configure the processing pipeline to use the middleware for the test. part of program configure Processing pipeline is shown below.   [Fact] public async Task MiddlewareTest_ReturnsNotFoundForRequest() { using varhst = await new hstBuilder().ConfigureWebhst(webBuilder => { webBuilder.UseTestServer().ConfigureServices(services => { services.AddMyServices(); }) .Configure(app => { app.UseMiddleware(); }); }) .StartAsync(); } After that you need to send requests with the HttpClient sample code is below. [Fact] public async Task MiddlewareTest_ReturnsNotFoundForRequest() { using varhst = await new hstBuilder().ConfigureWebhst(webBuilder => { webBuilder.UseTestServer().ConfigureServices(services => { services.AddMyServices(); }) .Configure(app => { app.UseMiddleware(); }); }) .StartAsync(); var response = await hst.GetTestClient().GetAsync("/"); } Assert the result and make an assertion of the opposite of the result that you expect. An embryonic run with a false positive assertion confirms that the test fails. when the middleware is performing Truly. Start test and confirm that the test is failed. In this example, the middleware returns a 404-status code which is NOT FOUND code when the root endpoint is requested. Make the first one test run with Assert.NotEqual (); which should be fail.   [Fact] public async Task MiddlewareTest_ReturnsNotFoundForRequest() { using varhst = await new hstBuilder().ConfigureWebhst(webBuilder => { webBuilder.UseTestServer().ConfigureServices(services => { services.AddMyServices(); }) .Configure(app => { app.UseMiddleware(); }); }) .StartAsync(); var response = await hst.GetTestClient().GetAsync("/"); Assert.NotEqual(HttpStatusCode.NotFound, response.StatusCode); } Change the assertion for test the middleware under normal operating ambiance. The final test uses Assert.Equal( );. Run the test a second time to confirm that it was successful.   [Fact] public async Task MiddlewareTest_ReturnsNotFoundForRequest() { using varhst = await new hstBuilder() .ConfigureWebhst(webBuilder => { webBuilder.UseTestServer().ConfigureServices(services => { services.AddMyServices(); }) .Configure(app => { app.UseMiddleware(); }); }) .StartAsync(); var response = await hst.GetTestClient().GetAsync("/"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } Looking to Hire Dedicated .ASP.Net Core Developer ? Contact Now. SEE HERE Send requests with HttpContext A test app is also sending a request using SendAsync(Action, CancellationToken). In this example, several checks are made when https:// example. com/A/Path/?and=query is done by the middleware.   [Fact] public async Task TestMiddleware_ExpectedResponse() { using varhst = await new hstBuilder() .ConfigureWebhst(webBuilder => { webBuilder.UseTestServer().ConfigureServices(services => { services.AddMyServices(); }) .Configure(app => { app.UseMiddleware(); }); }) .StartAsync(); var server = hst.GetTestServer(); server.BaseAddress = new Uri("https://example.com/A/Path/"); var context = await server.SendAsync(c => { c.Request.Method = HttpMethods.Post; c.Request.Path = "/and/file.txt"; c.Request.QueryString = new QueryString("?and=query"); }); Assert.True(context.RequestAborted.CanBeCanceled); Assert.Equal(HttpProtocol.Http11, context.Request.Protocol); Assert.Equal("POST", context.Request.Method); Assert.Equal("https", context.Request.Scheme); Assert.Equal("example.com", context.Request.hst.Value); Assert.Equal("/A/Path", context.Request.PathBase.Value); Assert.Equal("/and/file.txt", context.Request.Path.Value); Assert.Equal("?and=query", context.Request.QueryString.Value); Assert.NotNull(context.Request.Body); Assert.NotNull(context.Request.Headers); Assert.NotNull(context.Response.Headers); Assert.NotNull(context.Response.Body); Assert.Equal(404, context.Response.StatusCode); Assert.Null(context.Features.Get().ReasonPhrase); } SendAsync allow the direct configuration of an HttpContext object instead of using the HttpClient abstractions. Use SendAsync to control structures only available on the server, like HttpContext.Items or HttpContext.Features. As with the Previous example that tested for a 404 - Not Found response, check the other for every assert statement within the preceding test. The check confirms that the test fails correctly when the middleware is working normally. After you've confirmed that the false-positive test works, set the ultimate assert statements for the expected conditions and values of the test. Run it again to verify that the test passes. Conclusion Using Middleware unit testing you can test parts of code which is placed in program. You can also get more detail result of your testing. Using these you can customize data structures, like HttpContext, directly within the test. You can test from both sides correct or wrong.We hope this blog will be helpful for you to understand concept of unit testing a custom middleware in ASP.NET Core.
Kapil Panchal

Kapil Panchal

A passionate Technical writer and an SEO freak working as a Content Development Manager at iFour Technolab, USA. With extensive experience in IT, Services, and Product sectors, I relish writing about technology and love sharing exceptional insights on various platforms. I believe in constant learning and am passionate about being better every day.

Build Your Agile Team

Enter your e-mail address Please enter valid e-mail

Categories

Ensure your sustainable growth with our team

Talk to our experts
Sustainable
Sustainable
 
Blog Our insights
10 Executive Dashboard Examples for Consultants and CEOs
10 Executive Dashboard Examples for Consultants and CEOs

There is a principle behind every business. “If you don’t keep track of essentials, you won’t get clear direction, eventually causing your company to stumble.” To manage this scenario,...

How Spatial Data Analysis Improves Healthcare
How Spatial Data Analysis Improves Healthcare

Do you know when geospatial analysis took traction in healthcare? It was when John Snow, a London-based physician, used it to analyze the spread of cholera, which ultimately proved...

4 Types of Power BI Dashboards: Analytical, Strategic, Operational, and Tactical
4 Types of Power BI Dashboards: Analytical, Strategic, Operational, and Tactical

One interesting aspect you truly love about Power BI, as a CTO, is how it lets you step back and see the bigger picture of your business. Isn’t it? Without getting bogged down in minute...