10

私は現在、単体テストにScott Hanselman の HTTP コンテキスト モックを使用していました。これは MVC 3 でうまく機能し、後戻りすることはありませんでした。次のコードの呼び出しをテストするために使用しました。

public class PartialViewRenderer : IPartialViewRenderer
{
    public string Render(Controller controller, string viewName, object model)
    {
        if (string.IsNullOrEmpty(viewName))
            viewName = controller.ControllerContext.RouteData.GetRequiredString("action");

        controller.ViewData.Model = model;

        using (StringWriter sw = new StringWriter())
        {
            ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
            ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View,
                                                      controller.ViewData, controller.TempData, sw);
            viewResult.View.Render(viewContext, sw);

            return sw.GetStringBuilder().ToString();
        }
    }
}

アプリを最初に MVC 4 に変換したとき、問題が発生しました。実行時例外が発生していました。そこで、修正が必要なものを修正してみました。その結果、Hanselmans MockHelpers で次のメソッドを変更することになりました:

 public static HttpContextBase FakeHttpContext()
    {
        var context = new Mock<HttpContextBase>();
        var request = new Mock<HttpRequestBase>();
        var response = new Mock<HttpResponseBase>();
        var session = new Mock<HttpSessionStateBase>();
        var server = new Mock<HttpServerUtilityBase>();
        var cookies = new HttpCookieCollection();
        var items = new ListDictionary();

        request.Setup(r => r.Cookies).Returns(cookies);
        response.Setup(r => r.Cookies).Returns(cookies);

        context.Setup(ctx => ctx.Items).Returns(items);

        context.SetupGet(ctx => ctx.Request).Returns(request.Object);
        context.SetupGet(ctx => ctx.Response).Returns(response.Object);
        context.SetupGet(ctx => ctx.Session).Returns(session.Object);
        context.SetupGet(ctx => ctx.Server).Returns(server.Object);

        return context.Object;
    }

 public static void SetFakeControllerContext(this Controller controller, RouteData route)
    {
        var httpContext = FakeHttpContext();

        ControllerContext context = new ControllerContext(new RequestContext(httpContext, route), controller);

        controller.ControllerContext = context;
    }

ここでは、非常に単純な nUnit テストで、http コンテキストのこのモックにどのような変更を加える必要があるかを突き止めなければなりません (まだアサートを入れていません)。

    [Test]
    public void test()
    {
        _contactsController = _container.Resolve<ContactsController>();

        var route = new RouteData();

        route.Values.Add("controller", "ContactsController");
        route.Values.Add("action", "GetEditContactDetailsDialog");

        _contactsController.SetFakeControllerContext(route);

        var result = _contactsController.GetEditContactDetailsDialog("1");
    }

このテストを実行すると、オンラインの PartialViewRenderer.Render 呼び出しが爆発しViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName); ます。これが次のスタックトレースです。

System.Web.WebPages.DisplayModeProvider.<.ctor>b__2(HttpContextBase コンテキスト) で System.Web.WebPages.DefaultDisplayMode.CanHandleContext(HttpContextBase httpContext) で System.Web.WebPages.DisplayModeProvider.<>c__DisplayClass6.b__5(IDisplayMode モード) System.Linq.Enumerable.WhereListIterator 1.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable 1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 ソース) で System.Web.WebPages.DisplayModeProvider.GetAvailableDisplayModesForContext(HttpContextBase httpContext, IDisplayMode currentDisplayMode) で System.Web.Mvc.VirtualPathProviderViewEngine.GetPath(ControllerContext controllerContext, String[ ] location, String[] areaLocations, String locationsPropertyName, String name, String controllerName, String cacheKeyPrefix, Boolean useCache, String[]&searchedLocations)

そこに入ってDisplayModeProviderをモックすることはできないようです。 MVCソースコードごとに、これに対する解決策はありますか? 私はどこでもこれに対する解決策を見つけることができませんでした。

4

2 に答える 2

6

まず、モックを次のMockBehavior.Strictように初期化します。

var context = new Mock<HttpContextBase>(MockBehavior.Strict);

これを使用すると、DisplayMode との依存関係を見つけることができます。

次に、DisplayMode は asp.net mvc 4 の新機能です。

http://www.asp.net/whitepapers/mvc4-release-notes#_Toc303253810

したがって、Request.Browser使用する特定のビューのパラメーターを取得します。ブラウザー用のモックを追加します。

var browser = new Mock<HttpBrowserCapabilitiesBase>(MockBehavior.Strict);
var context = new Mock<HttpContextBase>(MockBehavior.Strict);
var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
var session = new Mock<HttpSessionStateBase>(MockBehavior.Strict);
var server = new Mock<HttpServerUtilityBase>(MockBehavior.Strict);
var cookies = new HttpCookieCollection();
var items = new ListDictionary();

browser.Setup(b => b.IsMobileDevice).Returns(false);

request.Setup(r => r.Cookies).Returns(cookies);
request.Setup(r => r.ValidateInput());
request.Setup(r => r.UserAgent).Returns("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11");
response.Setup(r => r.Cookies).Returns(cookies);

request.Setup(r => r.Browser).Returns(browser.Object);
context.Setup(ctx => ctx.Items).Returns(items);
于 2012-11-23T12:14:40.573 に答える
0

DisplayModeインターフェイスIDisplayModeを実装しているので、(Moqを使用して)注入するモックを作成できるはずです。DisplayModeProviderReflectionを介して呼び出すことがSetDisplayModeできる(保護された)メソッドがあります。

于 2012-11-12T17:58:45.633 に答える