0

コントローラーをテストするために http コンテキストを偽造しようとしています。私の環境は MVC 3 と Moq 4 です。これまでのところ、次のようないくつかのオプションを試しました。

を。

var searchController = new MySearchController(_mockResolver.Object.Resolve<IConfiguration>());
var mockContext = new Mock<ControllerContext>();
searchController.ControllerContext = mockContext.Object;
var result = searchController.Render();

b.

var searchController = new MopSearchController(_mockResolver.Object.Resolve<IConfiguration>());
searchController.MockControllerContext();
var result = searchController.Render();

public static class MockHttpHelper
{
    public static Mock<HttpContextBase> MockControllerContext(
                                this Controller controller, string path = null)
    {
        var mockHttpCtx = MockHttpHelper.MockHttpContext(path);
        var requestCtx = new RequestContext(mockHttpCtx.Object, new RouteData());
        var controllerCtx = new ControllerContext(requestCtx, controller);
        controller.ControllerContext = controllerCtx;
        return mockHttpCtx;
    }

    public static Mock<HttpContextBase> MockHttpContext(string path)
    {
        var mockHttpCtx = new Mock<HttpContextBase>();
        var mockReq = new Mock<HttpRequestBase>();

        mockReq.SetupGet(x => x.RequestType).Returns("GET");
        mockReq.SetupGet(req => req.Form).Returns(new NameValueCollection());
        mockReq.SetupGet(req => req.QueryString).Returns(new NameValueCollection());

        mockHttpCtx.SetupGet(x => x.Request).Returns(mockReq.Object);

        return mockHttpCtx;
    }
}

これらはどちらも機能しません。以下の例外が発生します。誰かが実際の例の方向に私を向けることができますか? 同じトピックについてネット上でかなりの数の質問を見てきましたが、日付 (2008 年から 2010 年までの投稿) と MVC バージョン (つまり 1 と 2) を考えると、何かが足りない/またはもっとモックしようとしているように感じます私がMVC3で必要とするよりも。

System.NullReferenceException : Object reference not set to an instance of an object.
at System.Web.Mvc.ChildActionValueProviderFactory.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.ValueProviderFactoryCollection.<>c__DisplayClassc.<GetValueProvider>b__7(ValueProviderFactory factory)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList(IEnumerable`1 source)
at System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.Controller.TryUpdateModel(TModel model)

ありがとう

4

1 に答える 1

0

はい、あなたが指摘したように、本当に欠けていたのは、コントローラーのValueProvider. このコントローラーを Get アクションで使用し、Post アクションを使用していない場合でも、コントローラーはValueProvider作成時にインスタンス化されるため、テスト シナリオで同じことを行う必要があります。コントローラーをテストするときに使用する基本クラスを次に示します。単体テストにはNBehave の NUnit ラッパーを使用しているため、必要に応じてSpecBase参照を無視してください

public abstract class MvcSpecBase<T> : SpecBase<T> where T : Controller
{
    protected T Controller { get; set; }

    protected string RelativePath = string.Empty;

    protected string AbsolutePath = string.Empty;

    protected void InitialiseController(T controller, NameValueCollection collection, params string[] routePaths)
    {
        Controller = controller;
        var routes = new RouteCollection();
        RouteConfig.RegisterRoutes(routes);
        var httpContext = ContextHelper.FakeHttpContext(RelativePath, AbsolutePath, routePaths);
        var context = new ControllerContext(new RequestContext(httpContext, new RouteData()), Controller);
        var urlHelper = new UrlHelper(new RequestContext(httpContext, new RouteData()), routes);
        Controller.ControllerContext = context;
        Controller.ValueProvider = new NameValueCollectionValueProvider(collection, CultureInfo.CurrentCulture);
        Controller.Url = urlHelper;
    }
}

次に、テストでコントローラーを作成し、次の行を呼び出します。

InitialiseController(controller, new FormCollection());
于 2013-02-08T23:22:50.513 に答える