如何从ControllerContext获取结果

时间:2011-07-05 09:55:40

标签: asp.net-mvc unit-testing

我的控制器操作返回一个自定义ActionResult,它根据某些验证逻辑执行成功或失败结果。这发生在ExecuteResult内。

我的问题是,如何查看结果?

到目前为止,这是测试:

[TestFixture]
public class FormActionResultTests
{
    TestController controller;

    [SetUp]
    public void SetUp()
    {
        ObjectFactory.Initialize(cfg =>
        {
            cfg.For<IFormHandler<TestModel>>().Use<TestModelHandler>();
        });

        controller = new TestControllerBuilder().CreateController<TestController>();
    }

    [Test]
    public void Valid_input_returns_success_result()
    {
        var result = controller.Test(new TestModel { IsValid = true, IsValid2 = true })
            .AssertResultIs<FormActionResult<TestModel>>();

        var context = controller.ControllerContext;

        result.ExecuteResult(context); 
        // how to verify result?

    }
}

public class TestController : Controller
{
    public ActionResult Test(TestModel model) {
        return new FormActionResult<TestModel>(model, this.Content("Success"), View(model));
    }
}

public class TestModel {
    public bool IsValid { get; set; }
    public bool IsValid2 { get; set; }
}

public class TestModelHandler : IFormHandler<TestModel>
{
    public void Handle(TestModel form, IValidationDictionary validationDictionary)
    {

    }
}

更新

这最终对我有用(使用NSubstitute):

    [Test]
    public void Valid_input_returns_success_result()
    {
        var result = new FormActionResult<TestModel>(new TestModel { IsValid = true, IsValid2 = true },
            new ContentResult { Content = "Success" }, new ContentResult { Content = "Failed" });

        var sb = new StringBuilder();
        var response = Substitute.For<HttpResponseBase>();
        response.When(x => x.Write(Arg.Any<string>())).Do(ctx => sb.Append(ctx.Arg<string>()));
        var httpContext = Substitute.For<HttpContextBase>();
        httpContext.Response.Returns(response);

        var controllerContext = new ControllerContext(httpContext, new RouteData(), new TestController());

        result.ExecuteResult(controllerContext);

        sb.ToString().ShouldEqual("Success");
    }

2 个答案:

答案 0 :(得分:1)

应该测试控制器在它们的情况下它们返回正确的ActionResult,并且ActionResultTest的Action或失败应该由ActionResultTest测试,它与控制器无关。单元测试意味着单个单元测试 - 但您在同一测试中测试控制器和ActionResult,这是不正确的。要测试ActionResult,首先想象一下ActionResult所做的一切,就是将结果写入HttpResponse。让我们重写您的代码,使用MoqStringWriter提供ControllerContext.HttpContext.HttpResponse.Output

[Test]
    public void Valid_input_returns_success_result()
    {
        var result = controller.Test(new TestModel { IsValid = true, IsValid2 = true })
            .AssertResultIs<FormActionResult<TestModel>>();

        var context = controller.ControllerContext;

        Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();

        StringWriter actionResultOutput = new StringWriter();

        mockHttpContext.Setup(x => x.Response.Output).Returns(actionResultOutput);


        context.HttpContext = mockHttpContext.Object;

        result.ExecuteResult(context); 
        // how to verify result? Examine actionResultOutput

    }

剩下的就是检查actionResultOutput。例如,如果您的操作结果设计为在验证正常时返回字符串“Success”,并在验证失败时返回“Error”,请将这些字符串与actionResultOutput.ToString()进行比较。如果您的结果视图生成的html更复杂,您可以使用HtmlAgilityPack更深入地检查输出

答案 1 :(得分:-1)

您应该编写一个关于Test-action的简单单元测试,并在返回的操作结果上断言。您不应该依赖于测试中的MVC框架。只需创建一个新的TestController实例并调用Test方法。