單元測試學習筆記03_Mock Framework介紹(Moq)_MVC專案的UnitTest介紹


在上一篇中介紹到有分所謂Stub跟Mock的做法
那在一般實作中較常用到的是模擬物件 Mock,因為很常我們處裡道的是
沒有回傳值的情況,因此比較著重在互動方式的驗證。

這類模擬物件的技法可以幫助我們在開發階段中不會
因為正式環境還沒準備好就無法驗證程式的窘境



但若要每次都自己寫Mock其實也滿費時的

因此就有推出許多Mock框架
在此先介紹Moq
也可輕鬆定義模擬物件包含visual studio intellisense整合使減輕測試的麻煩
此外Moq強型別的特性也能降低測試程式撰寫發生錯誤機率

新建一個MVC包含UnitTest的專案



在此順帶觀察MVC專案的UnitTest寫作方式
預設產生的示例


我們這裡已經事先準備寫好的一個BeginController 類別

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MVC_UniTestApp.Controllers
{
    public class BeginController : Controller
    {
        // GET: Begin
        public ActionResult Show()
        {
            ViewBag.Message = "早安你好";
            return View();
        }
    }
}


而我們在測試專案中的Controller目錄可再增加測試類與相關測試method



BeginControllerTest 類別

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using MVC_UniTestApp.Controllers;
using System.Web.Mvc;

namespace MVC_UniTestApp.Tests.Controllers
{
    [TestClass]
    public class BeginControllerTest
    {
        [TestMethod]
        public void ShowTest()
        {
            var ctrl = new BeginController();            
            var result = ctrl.Show() as ViewResult;
            Assert.AreEqual("早安你好",result.ViewBag.Message);            
        }
    }
}


執行後即可有相對測試結果產出


Moq下載方式
可透過指令
Install-Package Moq




這邊對BeginController擴充一個回傳尚未實作例外的Action

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MVC_UniTestApp.Controllers
{
    public class BeginController : Controller
    {
        // GET: Begin
        public ActionResult Show()
        {
            ViewBag.Message = "早安你好";
            return View();
        }

        //情境1.比方同事A要負責寫一個資料陳列的功能,同事B才能接續開發和進行驗證,但此時不想等,就可先叫同事A寫一個空殼的概念
        //情境2.比方還正在跟User洽談了解規格在開發過程只是先模糊知道有一個資料陳列的功能
        public virtual ActionResult List()
        {
            throw new NotImplementedException();
        }

    }
}


在搭配Moq開發時候
必須用virtual來修飾使其可被覆寫

導入Mock的單元測試撰寫
ListTest()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using MVC_UniTestApp.Controllers;
using System.Web.Mvc;
using Moq;

namespace MVC_UniTestApp.Tests.Controllers
{
    [TestClass]
    public class BeginControllerTest
    {
        [TestMethod]
        public void ShowTest()
        {
            var ctrl = new BeginController();
            var result = ctrl.Show() as ViewResult;
            Assert.AreEqual("早安你好", result.ViewBag.Message);
        }

        [TestMethod]
        public void ListTest()
        {
            var mock = new Mock<BeginController>();
            mock.Setup(c => c.List()).Returns(new ViewResult() { ViewName = "List" });

            var ctrl = mock.Object;

            var result = ctrl.List() as ViewResult;
            Assert.AreEqual("List",result.ViewName);
        }


    }
}





Moq框架主要核心也就是Mock Class型別
在其建構子中去透過指定特定物件型別來產生實體模擬出相應行為


在Mock中提供兩個方法



一個Setup
public ISetup<T> Setup(Expression<Action<T>> expression);
Specifies a setup on the mocked type for a call to a non-void (value-returning)
設定(Setup)目標要模擬的特定物件

一個Returns
IReturnsResult<TMock> Returns(TResult value);
Specifies the value to return.
預期回傳模擬的行為結果


public virtual T Object { get; }
Exposes the mocked object instance.
要取出模擬物件則透過.Object屬性來存取


這邊測試是可以過得
預設ViewName就是Action方法名稱
























 

留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header