c# - 在 mvc 2 中测试自定义 actionresult

标签 c# asp.net-mvc unit-testing

我有一个 actionresult 覆盖了 Execute(就像你做的那样)并且 actionresult 基本上接收一个模型,序列化它,然后通过 response.write(model as text) 将它写到响应中。

我环顾四周,但我看不到一种简单的方法来测试响应是否正确。我认为最好的方法是测试实例化自定义操作结果和模型,调用执行方法,然后在某个地方检查 Controller 上下文的响应。唯一的问题是,如何将响应输出作为字符串?我在某处读到你无法将响应输出流作为文本?如果是这样,我如何验证我的内容是否被写入响应流?我可以测试我的序列化程序以降低风险,但我想对 ExecuteResult 覆盖进行一些覆盖...

public class CustomResult: ActionResult
    {

        private readonly object _contentModel;
        private readonly ContentType _defaultContentType;

        public CustomResult(object contentModel, ContentType defaultContentType)
        {
            _contentModel = contentModel;
            _defaultContentType = defaultContentType;
        }

        public override void ExecuteResult(ControllerContext context)
        {
            context.HttpContext.Response.Write(serialized model);
        }

    } 

最佳答案

您可以获得文本形式的输出,但您必须做一些额外的工作才能使其全部可测试。

您需要 MVCContrib.TestHelper 来为所有 MVC 组件设置模拟。最重要的是,我有一些代码可以设置对请求相关部分的访问:

public class CustomTestControllerBuilder : TestControllerBuilder
{

    public CustomTestControllerBuilder()
    {
        var httpContext = new Moq.Mock<HttpContextBase>();
        var request = new Moq.Mock<HttpRequestBase>();
        var response = new Moq.Mock<HttpResponseBase>();
        var server = new Moq.Mock<HttpServerUtilityBase>();
        var _cache = HttpRuntime.Cache;

        httpContext.Setup(x=> x.Request).Returns(request.Object);
        httpContext.Setup(x => x.Response).Returns(response.Object);
        httpContext.Setup(x => x.Session).Returns(Session);
        httpContext.Setup(x => x.Server).Returns(server.Object);
        httpContext.Setup(x => x.Cache).Returns(_cache);


        var items = new Dictionary<object, object>();
        httpContext.Setup(x => x.Items).Returns(items);


        QueryString = new NameValueCollection();
        request.Setup(x => x.QueryString).Returns(QueryString);

        Form = new NameValueCollection();
        request.Setup(x => x.Form).Returns(Form);

        request.Setup(x => x.AcceptTypes).Returns((Func<string[]>)(() => AcceptTypes));

        var files = new WriteableHttpFileCollection();
        Files = files;
        request.Setup(x => x.Files).Returns(files);

        Func<NameValueCollection> paramsFunc = () => new NameValueCollection { QueryString, Form };
        request.Setup(x => x.Params).Returns(paramsFunc);

        request.Setup(x => x.AppRelativeCurrentExecutionFilePath).Returns(
                (Func<string>)(() => AppRelativeCurrentExecutionFilePath));
        request.Setup(x => x.ApplicationPath).Returns((Func<string>)(() => ApplicationPath));
        request.Setup(x => x.PathInfo).Returns((Func<string>)(() => PathInfo));
        request.Setup(x => x.RawUrl).Returns((Func<string>)(() => RawUrl));
        response.SetupProperty(x => x.Status);
        httpContext.SetupProperty(x=>x.User);

        var ms = new MemoryStream(65536);
        var sw = new StreamWriter(ms);
        response.SetupGet(x=>x.Output).Returns(sw);
        response.SetupGet(x => x.OutputStream).Returns(ms);

        response.Setup(x => x.Write(It.IsAny<string>())).Callback((string s) => { sw.Write(s); });
        response.Setup(x => x.Write(It.IsAny<char>())).Callback((char s) => { sw.Write(s); });
        response.Setup(x => x.Write(It.IsAny<object>())).Callback((object s) => { sw.Write(s); });

        //_mocks.Replay(HttpContext);
        //_mocks.Replay(request);
        //_mocks.Replay(response);

        TempDataDictionary = new TempDataDictionary();


        HttpContext = httpContext.Object;
    }

}
}

请注意,OutputStream 现在是 MemoryStream 而不是实际的网络连接。通过该设置,您只需要多几行即可获得将发送到客户端的输出:

 Result.ExecuteResult(c.ControllerContext);
 var ms = (MemoryStream)c.HttpContext.Response.OutputStream;
 c.HttpContext.Response.Output.Flush();
 ResultHtml = new UTF8Encoding().GetString(ms.GetBuffer());

关于c# - 在 mvc 2 中测试自定义 actionresult,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6367257/

相关文章:

Angular firebase - 使用 angularFireAuth 对服务进行单元测试

c# - 将 UTC DateTime 转换为 Xaml 中的本地时区?

c# - Unity3D : Performance with multi-camera rendering with a lot of spheric meshes

ajax - MVC Razor Ajax 从按钮点击调用

asp.net-mvc - 页面重新加载后,SignalR hub OnDisconnected 在不同浏览器中的触发时间

asp.net-mvc - 使用 MVC ViewBag 渲染 HTML

objective-c - 如何 TDD UIGestureRecognizers?

swift - Xcode - Swift 计算属性的奇怪代码覆盖率

c# - 为什么 ModelState.IsValid 在没有 [Required] 的情况下检查模型属性?

c# - 无法从 View 模型在用户控件中设置属性