iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 28
1
Modern Web

.Net Core 網站開發 101系列 第 28

Unit Test 單元測試

單元測試的特性跟優點在這邊就不贅述了,有興趣的可以參考官方文件,或者去上 91 大大的課。今天的重點會擺在如何在 ASP.NET Core MVC 專案中建立單元測試。.NET 有幾套主流的 test framework:xUnitNUnitMSTest,今天會以 MSTest 來作介紹。

建立測試專案 - MSTest

可以用 dotnet CLI 指定來建立:

  1. 建立測試專案
dotnet new mstest --output ironman2018.Tests
dotnet new mstest -o ironman2018.Tests
  1. 把測試目標加入參考:
cd ironman2018.Tests
dotnet add reference ../ironman2018/ironman2018.csproj

或者在 VS 2017 裡面建立:

  1. 在解決方案上點右鍵,「加入 > 新增專案」。
    https://ithelp.ithome.com.tw/upload/images/20181111/20107875w9BXNZb7Kg.png
  2. 選擇「Visual C# > 測試 > MSTest 測試專案」,習慣會以測試的目標專案名稱後面加上 .Tests 來命名。
    https://ithelp.ithome.com.tw/upload/images/20181111/20107875V52rcTBUnJ.png
  3. 建立成功後可以看到測試專案。
    https://ithelp.ithome.com.tw/upload/images/20181111/20107875ia9Uy5yneG.png
  4. ironman2018.Tests 專案中的參考點「右鍵 > 加入參考」。
    https://ithelp.ithome.com.tw/upload/images/20181111/201078753mamnvZ1BV.png
  5. 選擇「專案」,勾選我們的測試目標專案 ironman2018
    https://ithelp.ithome.com.tw/upload/images/20181111/20107875GD71YDzzsj.png

執行測試

建立完測試專案後,按 ctrl + R, A 就可以執行全部的測試了。因為剛建立只有一個沒做檢查的測試,會看到測試全部通過XD
https://ithelp.ithome.com.tw/upload/images/20181111/20107875JIrWKyZItJ.png

Controller 的單元測試

Controller 單元測試的重點應該在 Controller 中的行為或是否有回傳正確結果(與 View 無關)。例如我們測試下面這個 Controller:

public class HomeController : Controller
{
    private readonly ITodoRepository _todoRepository;

    public HomeController(ITodoRepository todoRepository)
    {
        _todoRepository = todoRepository;
    }

    public IActionResult Index()
    {
        var todos = _todoRepository.GetAll().ToList();

        return View(todos);
    }
}

其中有使用 Repository 模式來隔離資料介面,方便我們做測試。ITodoRepository 的介面定義:

public interface ITodoRepository : IDisposable
{
    void Insert(TodoModel instance);

    void Update(TodoModel instance);

    void Delete(TodoModel instance);

    TodoModel Get(Expression<Func<TodoModel, bool>> predicate);

    IQueryable<TodoModel> GetAll();

    void SaveChanges();
}

接下來預期對 TodoController.Index() 測試三個項目:

  1. 回傳類別為 ViewResult
  2. ViewDataDictionary.Model 的類別是 TodoModel
  3. ViewDataDictionary.Model 中有兩筆資料。

除了原本參考的 MSTest 外,這邊還有參考額外兩個 Library:

  1. NSubstitute:用來做 mock
  2. FluentAssertions:讓 assert 比較好閱讀 ,而且 MSTest 的 assert 方法比較少

完整的測試類別如下:

[TestClass]
public class TodoHomeControllerTests
{
    private HomeController todoController;

    [TestInitialize]
    public void SetUp()
    {
        ITodoRepository mockRepository = Substitute.For<ITodoRepository>();
        mockRepository.GetAll().Returns(new List<TodoModel>
        {
            new TodoModel
            {
                Title = "dotnet Core",
                CreatedAt = DateTime.Now,
                Completed = true
            },
            new TodoModel
            {
                Title = "unit test",
                CreatedAt = DateTime.Now,
                Completed = false
            },
        }.AsQueryable());

        todoController = new HomeController(mockRepository);
    }

    [TestMethod]
    public void Test_Index_Return_ViewResult_With_TodoModel()
    {
        // arrange
        
        // act
        var result = todoController.Index();
        
        // assert
        var okResult = result.Should()
            .BeOfType<ViewResult>().Subject;
        var todos = okResult.ViewData.Model.Should()
            .BeAssignableTo<IEnumerable<TodoModel>>().Subject;
        todos.Count().Should().Be(2);
    }
}

最後再按下 ctrl + R, A,就可以看到測試成功的畫面了!
https://ithelp.ithome.com.tw/upload/images/20181111/20107875eB9AiCBomw.png

參考資料


上一篇
Areas 區域
下一篇
Response Compression 壓縮回應
系列文
.Net Core 網站開發 10131

尚未有邦友留言

立即登入留言