Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The best way to test your routes for your ASP.NET Web API application is the integration test your endpoints.</p> <p>Here is simple Integration test sample for your ASP.NET Web API application. This doesn't mainly test your routes but it invisibly tests them. Also, I am using XUnit, Autofac and Moq here.</p> <pre><code>[Fact, NullCurrentPrincipal] public async Task Returns_200_And_Role_With_Key() { // Arrange Guid key1 = Guid.NewGuid(), key2 = Guid.NewGuid(), key3 = Guid.NewGuid(), key4 = Guid.NewGuid(); var mockMemSrv = ServicesMockHelper .GetInitialMembershipService(); mockMemSrv.Setup(ms =&gt; ms.GetRole( It.Is&lt;Guid&gt;(k =&gt; k == key1 || k == key2 || k == key3 || k == key4 ) ) ).Returns&lt;Guid&gt;(key =&gt; new Role { Key = key, Name = "FooBar" }); var config = IntegrationTestHelper .GetInitialIntegrationTestConfig(GetInitialServices(mockMemSrv.Object)); using (var httpServer = new HttpServer(config)) using (var client = httpServer.ToHttpClient()) { var request = HttpRequestMessageHelper .ConstructRequest( httpMethod: HttpMethod.Get, uri: string.Format( "https://localhost/{0}/{1}", "api/roles", key2.ToString()), mediaType: "application/json", username: Constants.ValidAdminUserName, password: Constants.ValidAdminPassword); // Act var response = await client.SendAsync(request); var role = await response.Content.ReadAsAsync&lt;RoleDto&gt;(); // Assert Assert.Equal(key2, role.Key); Assert.Equal("FooBar", role.Name); } } </code></pre> <p>There are a few external helpers I use for this test. The one of them is the <code>NullCurrentPrincipalAttribute</code>. As your test will run under your Windows Identity, the <code>Thread.CurrentPrincipal</code> will be set with this identity. So, if you are using some sort of authorization in your application, it is best to get rid of this in the first place:</p> <pre><code>public class NullCurrentPrincipalAttribute : BeforeAfterTestAttribute { public override void Before(MethodInfo methodUnderTest) { Thread.CurrentPrincipal = null; } } </code></pre> <p>Then, I create a mock <code>MembershipService</code>. This is application specific setup. So, this will be changed for your own implementation.</p> <p>The <code>GetInitialServices</code> creates the Autofac container for me.</p> <pre><code>private static IContainer GetInitialServices( IMembershipService memSrv) { var builder = IntegrationTestHelper .GetEmptyContainerBuilder(); builder.Register(c =&gt; memSrv) .As&lt;IMembershipService&gt;() .InstancePerApiRequest(); return builder.Build(); } </code></pre> <p>The <code>GetInitialIntegrationTestConfig</code> method is just initializes my configuration.</p> <pre><code>internal static class IntegrationTestHelper { internal static HttpConfiguration GetInitialIntegrationTestConfig() { var config = new HttpConfiguration(); RouteConfig.RegisterRoutes(config.Routes); WebAPIConfig.Configure(config); return config; } internal static HttpConfiguration GetInitialIntegrationTestConfig(IContainer container) { var config = GetInitialIntegrationTestConfig(); AutofacWebAPI.Initialize(config, container); return config; } } </code></pre> <p>The <code>RouteConfig.RegisterRoutes</code> method basically registers my routes. I also have a little extension method to create an <code>HttpClient</code> over the <code>HttpServer</code>.</p> <pre><code>internal static class HttpServerExtensions { internal static HttpClient ToHttpClient( this HttpServer httpServer) { return new HttpClient(httpServer); } } </code></pre> <p>Finally, I have a static class called <code>HttpRequestMessageHelper</code> which has bunch of static methods to construct a new <code>HttpRequestMessage</code> instance.</p> <pre><code>internal static class HttpRequestMessageHelper { internal static HttpRequestMessage ConstructRequest( HttpMethod httpMethod, string uri) { return new HttpRequestMessage(httpMethod, uri); } internal static HttpRequestMessage ConstructRequest( HttpMethod httpMethod, string uri, string mediaType) { return ConstructRequest( httpMethod, uri, new MediaTypeWithQualityHeaderValue(mediaType)); } internal static HttpRequestMessage ConstructRequest( HttpMethod httpMethod, string uri, IEnumerable&lt;string&gt; mediaTypes) { return ConstructRequest( httpMethod, uri, mediaTypes.ToMediaTypeWithQualityHeaderValues()); } internal static HttpRequestMessage ConstructRequest( HttpMethod httpMethod, string uri, string mediaType, string username, string password) { return ConstructRequest( httpMethod, uri, new[] { mediaType }, username, password); } internal static HttpRequestMessage ConstructRequest( HttpMethod httpMethod, string uri, IEnumerable&lt;string&gt; mediaTypes, string username, string password) { var request = ConstructRequest(httpMethod, uri, mediaTypes); request.Headers.Authorization = new AuthenticationHeaderValue( "Basic", EncodeToBase64( string.Format("{0}:{1}", username, password))); return request; } // Private helpers private static HttpRequestMessage ConstructRequest( HttpMethod httpMethod, string uri, MediaTypeWithQualityHeaderValue mediaType) { return ConstructRequest( httpMethod, uri, new[] { mediaType }); } private static HttpRequestMessage ConstructRequest( HttpMethod httpMethod, string uri, IEnumerable&lt;MediaTypeWithQualityHeaderValue&gt; mediaTypes) { var request = ConstructRequest(httpMethod, uri); request.Headers.Accept.AddTo(mediaTypes); return request; } private static string EncodeToBase64(string value) { byte[] toEncodeAsBytes = Encoding.UTF8.GetBytes(value); return Convert.ToBase64String(toEncodeAsBytes); } } </code></pre> <p>I am using Basic Authentication in my application. So, this class has some methods which construct an <code>HttpRequestMessege</code> with the Authentication header.</p> <p>At the end, I do my <em>Act</em> and <em>Assert</em> to verify the things I need. This may be an overkill sample but I think this will give you a great idea.</p> <p>Here is a great blog post on <a href="http://www.strathweb.com/2012/06/asp-net-web-api-integration-testing-with-in-memory-hosting/">Integration Testing with HttpServer</a>. Also, here is another great post on <a href="http://www.strathweb.com/2012/08/testing-routes-in-asp-net-web-api/">Testing routes in ASP.NET Web API</a>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload