接續上篇 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) 為例。
新建「Sample.WebAPI」的 WebAPI 2 專案,測試專案依然使用「Use-MvcRouteTester-To-TestRoute」:

紀錄
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 的檢測,更精準地達到我們想要涵蓋的領域。
不過測試方式還相當粗淺,若大家在實務上使用起來有什麼疑問,歡迎一起討論。
            