【发布时间】:2012-10-29 05:24:07
【问题描述】:
我是 MVC、单元测试、模拟和 TDD 的新手。我正在尝试尽可能地遵循最佳实践。
我为控制器编写了一个单元测试,如果返回正确的视图,我无法测试。如果我使用 ViewResult.ViewName 如果我没有在控制器中指定视图名称,那么测试总是会失败。如果我确实在控制器中指定了 ViewName,测试总是通过,即使视图不存在。
我也尝试过测试 Response.Status 代码,但它总是返回 200(代码取自 Darin Dimitrov 对 MVC3 unit testing response code 的回答)。我的目标是在创建新视图时进行经典的红绿重构,并在上线时避免 404 和 System.InvalidOperationException 错误,这可能吗?
代码如下。
public class BugStatusController : Controller
{
public ActionResult Index(){
return View(); // Test always fails as view name isn’t specified even if the correct view is returned.
}
public ActionResult Create(){
return View("Create"); // Test always passes as view name is specified even if the view doesn’t exist.
}
}
[TestFixture]
public class BugStatusTests
{
private ViewResult GetViewResult(Controller controller, string controllerMethodName){
Type type = controller.GetType();
ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);
object instance = constructor.Invoke(new object[] {});
MethodInfo[] methods = type.GetMethods();
MethodInfo methodInfo = (from method in methods
where method.Name == controllerMethodName
&& method.GetParameters().Count() == 0
select method).FirstOrDefault();
Assert.IsNotNull(methodInfo, "The controller {0} has no method called {1}", type.Name, controllerMethodName);
ViewResult result = methodInfo.Invoke(instance, new object[] {}) as ViewResult;
Assert.IsNotNull(result, "The ViewResult is null, controller: {0}, view: {1}", type.Name, controllerMethodName);
return result;
}
[Test]
[TestCase("Index", "Index")]
[TestCase("Create", "Create")]
public void TestExpectedViewIsReturned(string expectedViewName, string controllerMethodName){
ViewResult result = GetViewResult(new BugStatusController(), controllerMethodName);
Assert.AreEqual(expectedViewName, result.ViewName, "Unexpected view returned, controller: {0}, view: {1}", CONTROLLER_NAME, expectedViewName);
}
[Test]
[TestCase("Index", "Index")]
[TestCase("Create", "Create")]
public void TestExpectedStatusCodeIsReturned(string expectedViewName, string controllerMethodName)
{
var controller = new BugStatusController();
var request = new HttpRequest("", "http://localhost:58687/", "");
var response = new HttpResponse(TextWriter.Null);
var httpContext = new HttpContextWrapper(new HttpContext(request, response));
controller.ControllerContext = new ControllerContext(httpContext, new RouteData(), controller);
ActionResult result = GetViewResult(controller, controllerMethodName);
Assert.AreEqual(200, response.StatusCode, "Failed to load " + expectedViewName + " Error: " + response.StatusDescription);
}
}
【问题讨论】:
-
如果您的操作未返回命名视图,则您通过断言该视图名称为空来验证该行为。如果操作返回一个命名视图,则断言视图名称存在于视图结果中。我不明白这种方法有什么问题?
标签: c# asp.net-mvc unit-testing tdd