DIに対してユニットテストを考える
前回で、ユニットテストの最低限の環境を整えました。
今回は、以前に利用したDIに対してテストを書いてみます。
基本的な考え方
特別なことは必要なくて、コントローラーのコンストラクタやアクションに対して、依存オブジェクトを直接与えるだけです。
ですが、せっかくInterfaceを定義してあるので、下記のようなテスト用のダミークラスを導入します。
class DummyValueService : Services.IValueService { public int GetValue() { return 42; } }
それに伴ってテストは下記のようになります。
[Fact] public void Test1() { var service = new DummyValueService(); var controller = new NiceController(service, service); var view = controller.Index(service) as ViewResult; var expected = 42; var actual1 = view.ViewData["constructorInject1"]; var actual2 = view.ViewData["constructorInject2"]; var actual3 = view.ViewData["actionInject"]; Assert.Equal(expected, actual1); Assert.Equal(expected, actual2); Assert.Equal(expected, actual3); }
このようにDIを導入したことでコントローラーのテストが容易に記述できるようになっています。
が!
こんなこと(ダミークラス作成)をいちいちやっていられないのです!
そんなことを避けるために、モックフレームワークを導入する
というわけで、モックフレームワークを導入します。
C#で人気のモックフレームワークと言えばMoqです。
ユニットテストフレームワークは色々人気を分けていますが、モックフレームワークではMoqが一番人気なのではないでしょうか。
準備
Moqですが、現時点では公式の.NET Core対応パッケージは用意されていないようです。
しかし.NET Core対応版のフォークがあるようなのでそれを利用します。
そのためにまずは以下のようにNugetFeedを追加します。
[Tools]-[Options]-[NuGet Package Manager]-[Package Sources]
右上の十字アイコンより以下を追加します。 Source : https://www.myget.org/F/aspnet-contrib/api/v3/index.json
Moqを追加する
テストプロジェクトのproject.jsonに下記を追加します。
"moq.netcore": "4.4.0-beta8", "System.Diagnostics.TraceSource": "4.0.0"
私の環境では、System.Diagnostics.TraceSourceを追加しないとNotFoundExceptionが発生しました。
モックフレームワークを利用したテストを書く
で、Moqを利用したテストは下記のようになります。
[Fact] public void Test1() { var mock = new Moq.Mock<Services.IValueService>(); mock.Setup(x => x.GetValue()).Returns(42); var controller = new NiceController(mock.Object, mock.Object); var view = controller.Index(mock.Object) as ViewResult; var expected = 42; var actual1 = view.ViewData["constructorInject1"]; var actual2 = view.ViewData["constructorInject2"]; var actual3 = view.ViewData["actionInject"]; Assert.Equal(expected, actual1); Assert.Equal(expected, actual2); Assert.Equal(expected, actual3); }
最初の例と比べてモックフレームワークの良いところは、例えばインタフェースの一部実装などができます。
ダミークラスを作成する場合はインタフェースのメソッドを全て実装する必要がありますが、モックフレームワークを利用すればテストに必要なメソッドのみをモック(物まね)させることができます。