ASP.NET MVC Route Unit Test - Part.3 - MvcRouteTester - WebAPI Project

接續上篇 ASP.NET MVC Route Unit Test - Part.2 的內容中,提到如何使用「MvcRouteTester」元件來測試 MVC 專案的 RouteConfig + Controller。

接下來這篇則使用 WebAPI 2 專案,紀錄如何結合 WebApiConfig Route 與 ApiController 的測試開發。

前言

在上篇提到 MvcRouteTester 採用 Fluent Extensions 描述方式,包含了以下功能:

這篇就以 API Route 為主題,進行說明。

接下來處理針對 ASP.NET WebAPI 2 的 WebApiConfig 與 ApiController 的組合,如何實作相關測試。以 ImagesController (API) 為例。

目標對象:System.Web.Http.HttpConfiguration

新建「Sample.WebAPI」的 WebAPI 2 專案,測試專案依然使用「Use-MvcRouteTester-To-TestRoute」:

範例專案:GitHub

紀錄

API Route Test 簽章

  • RouteAssert.HasApiRoute
  • RouteAssert.NoApiRoute
  • RouteAssert.ApiRouteDoesNotHaveMethod
  • RouteAssert.ApiRouteMatches
  • RouteAssert.NoApiRouteMatches
  • HttpConfiguration 擴充功能:ShouldMap (重點項目,可與 ApiController 層一起測試)

ASP.NET WebAPI 範例

var apiRoutesConfig = new HttpConfiguration();
apiRoutesConfig .Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);


//// 驗證/api/customer/1是否符合規則
RouteAssert.HasApiRoute(apiRoutesConfig , "/api/customer/1", HttpMethod.Get);


//// 驗證/api/customer/1是否符合規則
var expectation = new { controller = "Customer", action= "get", id = "1" };
RouteAssert.HasApiRoute(apiRoutesConfig , "/api/customer/1", HttpMethod.Get, expectation);

接下來,就在 WebAPI 專案,建立新的 ImagesController

接下來,在「Use_MvcRouteTester_To_TestRoute」測試專案上,建立「ImagesApiRouteTest」

using Microsoft.VisualStudio.TestTools.UnitTesting;
using MvcRouteTester;
using Sample.WebAPI;
using Sample.WebAPI.Controllers;
using System.Net.Http;
using System.Web.Http;

namespace Use_MvcRouteTester_To_TestRoute.Routes
{
    [TestClass]
    public class ImagesApiRouteTest
    {
        private HttpConfiguration testConfig;

        public ImagesApiRouteTest()
        {
            //// Arrange
            testConfig = new HttpConfiguration();
            WebApiConfig.Register(testConfig);
        }

        /// <summary>
        /// api/Images/Original/type/1 測試
        /// </summary>
        [TestMethod]
        public void ImagesRoute_RouteWith_Controller_Index_Action_Type_Id_ShouldMapToRenderOriginal()
        {
            ...
        }
    }
}

這時直接跑測試,會收到一個 紅燈,如下:

所以會在初始化時,加上以下設定:

HttpConfiguration.EnsureInitialized();

結果 綠燈

接著回頭來看一下 ImagesController 的 測試案例。

在上一篇使用 MVC 專案時,提到 HttpMethod 檢測的問題,那麼加上測試案例到 WebAPI 專案,如下:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using MvcRouteTester;
using Sample.WebAPI;
using Sample.WebAPI.Controllers;
using System.Net.Http;
using System.Web.Http;

namespace Use_MvcRouteTester_To_TestRoute.Routes
{
    [TestClass]
    public class ImagesApiRouteTest
    {
        ...

        /// <summary>
        /// api/Images/Original/type/1 測試
        /// </summary>
        [TestMethod]
        public void ImagesRoute_RouteWith_Controller_Index_Action_Type_Id_ShouldMapToRenderOriginal()
        {
            testConfig.ShouldMap("/api/Images/Original/type/1")
                      .To<ImagesController>(c => c.RenderOriginal(string.Empty, string.Empty));

            testConfig.ShouldMap("/api/Images/Original/type/1")
                      .To<ImagesController>(HttpMethod.Get, c => c.RenderOriginal(string.Empty, string.Empty));

            testConfig.ShouldMap("/api/Images/Original/type/1")
                      .To<ImagesController>(HttpMethod.Post, c => c.RenderOriginal(string.Empty, string.Empty));
        }
    }
}

因為事前的設定 HttpGet,我們預期 http://localhost/api/Images/Original/type/1 只能接受 HttpMethod.Get 方式被呼叫。

由下方實際的案例來看,也能正常的抓出問題。(握拳)

所以可以將測試案例調整為

using Microsoft.VisualStudio.TestTools.UnitTesting;
using MvcRouteTester;
using Sample.WebAPI;
using Sample.WebAPI.Controllers;
using System.Net.Http;
using System.Web.Http;

namespace Use_MvcRouteTester_To_TestRoute.Routes
{
    [TestClass]
    public class ImagesApiRouteTest
    {
        ...

        /// <summary>
        /// 使用 HttpMethod Get 進行 api/Images/Original/type/1 測試
        /// </summary>
        [TestMethod]
        public void ImagesRoute_WithHttpMethod_Get_RouteWith_Controller_Index_Action_Type_Id_ShouldMapToRenderOriginal()
        {
            testConfig.ShouldMap("/api/Images/Original/type/1")
                      .To<ImagesController>(c => c.RenderOriginal(string.Empty, string.Empty));

            testConfig.ShouldMap("/api/Images/Original/type/1")
                      .To<ImagesController>(HttpMethod.Get, c => c.RenderOriginal(string.Empty, string.Empty));
        }

        /// <summary>
        /// 預期 沒有 HttpMethod Post 方法,可以呼叫到 api/Images/Original/type/1 測試
        /// </summary>
        [TestMethod]
        public void ImagesRoute_NoHttpMethod_Post_RouteWith_Controller_Index_Action_Type_Id_ShouldMapToRenderOriginal()
        {
            testConfig.ShouldMap("/api/Images/Original/type/1")
                      .ToNoMethod<ImagesController>(HttpMethod.Post);
        }
    }
}

以上是針對 ASP.NET WebAPI 2 專案 ( Sample.WebAPI ) 的 WebApiConfig 與 ApiController 進行測試開發。

結論

透過上述的方法,我們也能針對 WebApiConfig + ApiController 進行整合性的測試。搭配 HttpMethod 的檢測,更精準地達到我們想要涵蓋的領域。

不過測試方式還相當粗淺,若大家在實務上使用起來有什麼疑問,歡迎一起討論。

參考資料

●  MvcRouteTester GitHub
●  MvcRouteTester Wiki Usage