我是 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);
}
}