私は ASP.NET MVC 4 用のカスタム RazorViewEngine を作成していますが、基本クラスがすべての種類の例外をスローする BuildManager および VirtualPathProvider に到達するものを呼び出しているため、ユニット テストに苦労しています。作成したすべての新しいテスト内で、何か他のものをスタブ化する必要がありました。これは、基になるメカニズムが、スタブ化していないオブジェクトを呼び出しており、「オブジェクト参照がオブジェクトのインスタンスに設定されていません」をスローするためです。
そこで、エンジンの基本クラスへの呼び出しをラップできるようにする、このようなインターフェイスを作成しました。
internal interface IViewEngineDelegate
{
Func<ControllerContext, string, IView> CreatePartialView { get; set; }
Func<ControllerContext, string, string, IView> CreateView { get; set; }
Func<ControllerContext, string, bool> FileExists { get; set; }
Func<ControllerContext, string, bool, ViewEngineResult> FindPartialView { get; set; }
Func<ControllerContext, string, string, bool, ViewEngineResult> FindView { get; set; }
}
これで、本番コードで次のことができます。
public class CsEmbeddedRazorViewEngine : RazorViewEngine
{
private readonly IViewEngineDelegate _viewEngineDelegate;
public CsEmbeddedRazorViewEngine()
{
_viewEngineDelegate = new ViewEngineDelegate
{
CreatePartialView = base.CreatePartialView,
CreateView = base.CreateView,
FileExists = base.FileExists,
FindPartialView = base.FindPartialView,
FindView = base.FindView
};
}
internal CsEmbeddedRazorViewEngine(IViewEngineDelegate viewEngineDelegate)
{
_viewEngineDelegate = viewEngineDelegate;
}
protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
// TODO: Do something.
return _viewEngineDelegate.CreatePartialView(controllerContext, partialPath)
}
}
最後に、このように呼び出しをスタブ化してテストできます。
ViewEngineDelegate engineDelegate = new ViewEngineDelegate
{
CreatePartialView = (controllerContext, partialPath) => FakeViewFactory.Instance.Create(controllerContext, partialPath),
};
CsEmbeddedRazorViewEngine engine = new CsEmbeddedRazorViewEngine(engineDelegate);
少し考えた後、私は設計を過剰に設計したと思うので、これを行うことを考えたので、より簡単なアプローチを採用することにしました。
public class CsEmbeddedRazorViewEngine : RazorViewEngine
{
protected sealed override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
// TODO: Do something.
return default(IView);
}
protected virtual IView CreatePartialViewCore(ControllerContext controllerContext, string partialPath)
{
return base.CreatePartialView(controllerContext, partialPath);
}
}
私はこれらのアプローチのいずれにも本当に満足していません。それが私がそれについて投稿している理由です。それを行うためのより良い方法があるかどうか疑問に思っています。おそらくそれは私だけであり、これらは許容/合理的なアプローチです.