我为控制器编写了单元测试,如果返回正确的视图,我无法测试.如果我使用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}",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_name,expectedVIEwname); } [Test] [TestCase("Index","Create")] public voID TestExpectedStatusCodeIsReturned(string expectedVIEwname,string controllerMethodname) { var controller = new BUGStatusController(); var request = new @R_502_6822@Request("","@R_502_6822@://localhost:58687/",""); var response = new @R_502_6822@Response(TextWriter.Null); var @R_502_6822@Context = new @R_502_6822@Contextwrapper(new @R_502_6822@Context(request,response)); controller.ControllerContext = new ControllerContext(@R_502_6822@Context,new RouteData(),controller); ActionResult result = GetVIEwResult(controller,controllerMethodname); Assert.AreEqual(200,response.StatusCode,"Failed to load " + expectedVIEwname + " Error: " + response.StatusDescription); }}解决方法
I’m new to MVC,Unit Testing,Mocking and TDD. I’m trying to follow best practice as closely as possible.
我感到开心,越来越多的开发人员开始为他们的代码编写单元测试,所以恭喜你走在正确的道路上.
if I don’t specify the vIEw name in the controller. If I do specify the VIEwname in the controller the test always passes,even if the vIEw doesn’t exist.
当您在VIEw方法中未指定视图名称时,将指示MVC引擎呈现默认视图,例如
public ActionResult Index() { return VIEw(); }
上面的代码将返回一个空的视图名,这意味着渲染的视图将是 *** 作的名称,在这种情况下它将是Index.
因此,如果要测试一个 *** 作返回默认视图,则必须测试返回的视图名称是否为空
Test always passes as vIEw name is specifIEd even if the vIEw doesn’t exist.
为了解释这里发生了什么,我将首先解释动作过滤器的工作原理.
基本上有四种类型的滤波器
>异常过滤器
>授权过滤器
>动作过滤器
>结果过滤器
我会专注于行动和结果过滤器
动作过滤器由IActionFilter接口定义
public interface IActionFilter{ // Summary: // Called after the action method executes. // voID OnActionExecuted(ActionExecutedContext filterContext); // // Summary: // Called before an action method executes. // voID OnActionExecuting(ActionExecutingContext filterContext);}
结果过滤器由IResultFilter接口定义
public interface IResultFilter{ // Summary: // Called after an action result executes. // voID OnResultExecuted(ResultExecutedContext filterContext); // // Summary: // Called before an action result executes. // voID OnResultExecuting(ResultExecutingContext filterContext);}
当执行控制器的动作时,按以下特定顺序执行以下过滤器:
IActionFilter.OnActionExecutingIActionFilter.OnActionExecutedIResultFilter.OnResultExecutingIResultFilter.OnResultExecuted
当执行一个动作时,另一个组件负责处理从您的 *** 作返回的ActionResult,并呈现正确的HTML以将其发送回客户端,这是处理结果时
这种干涉分离的关键是美观和关键,允许我们单位测试我们的控制器的行动,否则,如果它们耦合,我们将无法单独测试单独测试结果的行动
现在,RazorVIEwEngine尝试在执行 *** 作后(当处理结果时)找到一个视图,这就是为什么您的测试返回true,即使物理视图不存在.这是预期的行为,并记住您需要隔离测试控制器的 *** 作.只要您在单元测试中断言预期视图呈现,您就可以完成单元测试.
如果您想声明物理视图存在,那么您将会讨论一些特定的集成测试:功能测试或用户验收测试 – 这些测试需要使用浏览器实例化您的应用程序,而不是单元测试
现在您可以手动编写单元测试(如果您进入单元测试世界,这是一个很好的练习),但是,我想推荐一些可以帮助您编写单元的MVC测试框架测试真的很快
> https://github.com/robdmoore/FluentMVCTesting
> http://mvccontrib.codeplex.com/wikipage?title=TestHelper&referringTitle=Documentation
关于这些框架的一些个人评论
根据我的经验,MVC Contrib具有比Fluent MVC测试更多的功能,由于我使用MVC 4,我无法在Visual Studio 2012中使用它,所以我使用两者的组合(这是一个脏解决方法,直到我找到一个更好的方法)
这就是我所做的:
var testControllerBuilder = new TestControllerBuilder(); // this is from MVC Contribvar controller = new MovIEsController( this.GetMock<IMovIEqueryManager>().Object);testControllerBuilder.InitializeController(controller); // this allows me to use the Session,Request and Response objects as mock objects,again this is provIDed by the MVC Contrib framework// I should be able to call something like this but this is not working due to some problems with DLL versions (hell DLL's) between MVC Controb,Moq and MVC itself// testControllerBuilder.CreateController<MovIEsController>();controller.WithCallTo(x => x.Index(string.Empty)).ShouldRenderdefaultview(); // this is using Fluent MVC Testing// again instead of the above line I Could use the MVC Contrib if it were working....// var res = sut.Index(string.Empty);// res.AssertVIEWrendered().ForVIEw("Index");
我希望这有助于=)快乐的编码!
总结以上是内存溢出为你收集整理的c# – 如何单元测试使用MVC ASP.Net返回正确的视图?全部内容,希望文章能够帮你解决c# – 如何单元测试使用MVC ASP.Net返回正确的视图?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)