既存の MVC Controller に対してテストコードを書く必要があって、その時にはまったこと。
やりたいこと
- FindPartialView を(とりあえず)通したい
環境
- Windows 10 Pro
- Visual Studio 2019
- .NET Framework 4.7.2
最初に
Controller の中でViewEngines.Engines.FindPartialView
しているところがあり、単純にテストクラスでnew TestController().Hoge()
みたいに実行すると
ControllerContext がない!
とかいろいろ怒られる。
Moq で何とかなる?
ControllerContext の Mock 作ればできるかも、と思ってやってみたものの、FindPartialView の実行に必要な ControllerContext の値が調べきれず。。
さらにいろいろ調べたところ、ViewEngines.Engines 自体に Mock の値を登録してしまうという記事を発見。
やってみる
上記記事を参考に実装。
// RouteDatavarrouteData=newRouteData();routeData.Values.Add("action","[ActionName]");routeData.Values.Add("controller","[ControllerName]");// ControllerContextvarmock=newMock<ControllerContext>();mock.SetupGet(m=>m.RouteData).Returns(routeData);// Viewvarview=newMock<IView>();varviewEngine=newMock<IViewEngine>();varviewEngineResult=newViewEngineResult(view.Object,viewEngine.Object);viewEngine.Setup(e=>e.FindPartialView(It.IsAny<ControllerContext>(),It.IsAny<string>(),It.IsAny<bool>())).Returns(viewEngineResult);// ViewEnginesの削除・登録ViewEngines.Engines.Clear();ViewEngines.Engines.Add(viewEngine.Object);// Controller.ControllerContextにMockオブジェクトを設定varcontroller=newTestController();controller.ControllerContext=mock.Object;
実行時にエラーになるので、RouteData.Values に Controller の追加は必要。
Mock で生成した View と ViewEngine で作った ViewEngineResult を FindPartialView の戻りとして設定してあげる。さらに、ViewEngines.Engines に上記 ViewEngine を登録すればテスト実行可能。
改善の余地あり
上記コードだと、複数の FindPartialView があるときでも、常に同じ戻りとなる。e.FindPartialView(It.IsAny<ControllerContext>(), It.IsAny<string>(), It.IsAny<bool>())
の第二引数を It.IsAny() ではなく、指定可能にするような実装にしつつ、指定した値に対応した View を生成するようにすれば、いろいろなパターンに対応できそう。