■単体テストを準備/実施する
これで、アプリケーション側のリポジトリ・クラス対応は完了だ。続いて、テスト・プロジェクト側でテストを準備/実施していこう。テスト・プロジェクト側で用意しなければならないのは、テスト用のリポジトリ・クラスと、テスト・クラス本体である。
[1]単体テスト用のリポジトリ・クラスを準備する
データベースを準備しなくてもテストが実施できるよう、まずは単体テスト用のBooksTestRepositoryクラスを準備しておこう
using System;
using System.Collections.Generic;
using MvcTemplate.Models;
namespace MvcTemplate.Tests.Models
{
class BooksTestRepository : IBooksRepository
{
public List<Book> GetAllBooks()
{
// ダミーのBookエンティティを生成し、リストとして返す
var books = new List<Book>();
for (var i = 0; i < 5; i++)
{
books.Add(
new Book()
{
Isbn = "978-4-7980-3080-" + i.ToString(),
Title = "書名" + i.ToString(),
Price = 2000 + i,
Publish = "出版社" + i.ToString(),
Published = DateTime.Now.AddDays(i)
}
);
}
return books;
}
public Book CreateBook(Book bok)
{
// 何もせず、引数をそのまま返す
return bok;
}
}
}
|
Public Class BooksTestRepository : Implements IBooksRepository
Public Function GetAllBooks() As System.Collections.Generic.List(Of Book) Implements IBooksRepository.GetAllBooks
' ダミーのBookエンティティを生成し、リストとして返す
Dim books = New List(Of Book)
For i = 2 To 5
books.Add(
New Book() With {
.Isbn = "978-4-7980-3080-" & i.ToString(),
.Title = "書名" & i.ToString(),
.Price = 2000 + i,
.Publish = "出版社" & i.ToString(),
.Published = DateTime.Now.AddDays(i)
}
)
Next
Return books
End Function
Public Function CreateBook(bok As Book) As Book Implements IBooksRepository.CreateBook
' 何もせず、引数をそのまま返す
Return bok
End Function
End Class
|
|
リスト11 単体テスト用の、ダミー・データを返すリポジトリ・クラス(上:BooksTestRepository.cs、下:BooksTestRepository.vb) |
。BooksTestRepositoryクラスでは、前出のIBooksRepositoryインターフェイスを実装する必要がある。Indexメソッドはデータベースに接続する代わりに、ダミーのBookエンティティを返すだけのコードを、Createメソッドは引数に渡されたBookエンティティをそのまま返すだけのコードを、それぞれ準備する。
[2]テスト・コードを準備する
これで、コントローラをテストするための準備が整ったので、いよいよテスト・メソッドを記述する。
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MvcTemplate.Controllers;
using MvcTemplate.Tests.Models;
using System.Web.Mvc;
using MvcTemplate.Models;
[TestMethod]
public void Index()
{
// アクションを実行
var ctrl = this.GetController();
var result = ctrl.Index() as ViewResult;
// 結果の検証
Assert.AreEqual(5, ((List<Book>)result.Model).Count);
}
[TestMethod]
public void Create()
{
// アクションを実行
var ctrl = this.GetController();
var result = ctrl.Create(
new Book()
{
Isbn = "978-4-7980-3080-0",
Title = "書名",
Price = 2000,
Publish = "出版社",
Published = DateTime.Now
}
);
// 結果の検証
Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));
}
private BooksController GetController()
{
// テスト用のリポジトリ・クラスを、コントローラにセット
return new BooksController(
new BooksTestRepository());
}
|
Imports MvcTemplateVb.MvcTemplateVb
Imports System.Web.Mvc
<TestMethod()>
Public Sub Index()
' アクションを実行
Dim ctrl = Me.GetController()
Dim result = DirectCast(ctrl.Index(), ViewResult)
' 結果の検証
Assert.AreEqual(5, DirectCast(result.Model, List(Of Book)).Count)
End Sub
<TestMethod()>
Public Sub Create()
' アクションを実行
Dim ctrl = Me.GetController()
Dim result = ctrl.Create(
New Book() With {
.Isbn = "978-4-7980-3080-0",
.Title = "書名",
.Price = 2000,
.Publish = "出版社",
.Published = DateTime.Now
}
)
' 結果の検証
Assert.IsInstanceOfType(result, GetType(RedirectToRouteResult))
End Sub
Private Function GetController() As BooksController
' テスト用のリポジトリ・クラスを、コントローラにセット
Return New BooksController(
New BooksTestRepository())
End Function
|
|
リスト12 リポジトリ・クラスを介したアクションをテストするコード(上:BooksControllerTest.cs、下:BooksControllerTest.vb) |
テスト用のリポジトリ・クラスを適用するには、コントローラ・クラスのコンストラクタに、引数としてテスト・リポジトリを渡すだけだ(太字部分)。
後は、先にも示したように、アクション・メソッドを呼び出し、その結果をAssertクラスで検証するだけでよい。Indexテスト・メソッドでは、Indexアクションで得られたモデル(リスト)が5個のエンティティを含んでいることを、Createテスト・メソッドでは、Createアクションの結果、RedirectToRouteResultクラスが返されることを、それぞれチェックしている。
■
以上、今回はアプリケーションをテストする方法、モック・ライブラリMoqの基本、そして、データベース連携アプリケーションのテストを容易にする定石でもあるリポジトリ・クラスについて解説した。実践的なアプリケーションでは、あまたのコードが登場するが、まずは本稿で紹介したアプローチを理解しておけば、ほぼ同じ要領でテストを実施できるはずだ。
さて、本連載もこの回で最終回。ASP.NET MVCには、ここで紹介したほかにもさまざまな機能が含まれているが、まずは、本連載で紹介した機能を理解できていれば、基本的なアプリケーションは開発できるようになっているはずだ。前回の連載も併せてこの連載が、読者諸兄にとってASP.NET MVCを学習する手掛かりとなれば幸いである。
Insider.NET 記事ランキング
本日
月間