如何测试 Asp.Net MVC 视图的渲染是否没有异常?
我在我的申请中发现了一个小问题。
我将主应用程序的命名空间从 MyApp.Models
更改为 MyApp.ViewModels
,这样命名空间总体上就不那么混乱了(因为该命名空间只有视图模型,没有视图模型)商业模式)。我更改了我能找到的所有参考文献,包括我的观点,并且重新运行了所有单元测试并浏览了应用程序,一切看起来都很好。
几天后,我收到报告称注册页面在打开时出现错误。查看后发现我忘记修复注册页面上的名称空间,因此无法编译视图。
这让我很担心。单元测试的全部要点,也是 Asp.Net MVC 的最大诱惑之一,是能够通过自动单独测试所有内容来对您的应用程序充满信心,以便您立即知道您的修改何时会破坏系统的某些部分。现在的观点似乎是其中的一个主要漏洞。
需要明确的是,我知道您可以打开预编译视图。但是,我不喜欢这个选项,因为一直打开它不是一个好主意(因为它使得编译新版本非常非常慢),并且为此拥有一个单独的配置方案意味着用户可以请记住尝试使用该配置方案进行编译以检查视图编译错误。
这也完全绕过了对可能发生的运行时错误的检查。例如,假设您更改了强类型视图所需的视图模型。然后,您将更新单元测试以确保 Controller.Action()
返回具有正确视图模型类型的视图结果,但这无法确保实际视图已正确更新对于新视图,但这种情况会导致运行时异常。这是很容易发生的情况,特别是因为两个视图模型中的差异仅在视图中使用的部分中可见。
可能导致视图中运行时异常的代码的其他示例包括不正确的循环(可能由视图模型中的更改引起)、检查用户角色的代码(因此仅向具有凭据的用户显示按钮)、不正确的强制转换(例如,用于转换集合到选择列表中),对集合进行排序的代码不正确(集合在显示中的排序方式可以解释为视图问题,而不是控制器或视图模型问题),如果用于文件位置的字符串无法正常工作(T4MVC与某些东西集成得不太好,例如Telerik的脚本注册系统)等等......
在我看来,有很多东西可以导致渲染视图过程中发生异常,我可以似乎没有找到任何方法来创建单元或集成测试来确定这些情况何时发生。如果我不必检查每个页面以确保我错过了标准单元测试应该能够捕获的编译时或运行时错误,我会感觉更舒服。
我必须采取哪些选择才能做到这一点?
我宁愿远离 WaTiN 和其他 GUI 测试工具,因为对此我对页面的实际显示不感兴趣,我只想知道视图是否呈现或是否发生异常,并且不需要开销Watin 为每个测试运行一个 IE 实例(我也认为如果我稍后进行持续集成,这会导致问题)。
I have come up with a small issue in my application.
I changed the namespace of my main application to be from MyApp.Models
to MyApp.ViewModels
so that the namespaces were less confusing overall (since that namespace only has view models and no business models). I changed all the references I could find, including in my views, and I re-ran all my unit tests and went through the application, and all seemed fine.
A few days later I got a report that the registration page had an error when it was brought up. After looking it turns out I forgot to fix the namespace on the registration page, and thus it was failing to compile the view.
This worries me. The whole point of unit testing, and one of the biggest lures of Asp.Net MVC, is to be able to have confidence in your application by having everything tested individually automatically so that you know immediately when your modification breaks parts of the system. Views right now seem like a major hole in this.
To be clear, I am aware you are able to turn on pre-compiling a views. However, I do not like this option as it's not a good idea to have this on all the time (as it makes compiling a new build very, very slow), and having a separate configuration scheme for this means it's up to the user to remember to attempt to compile with that configuration scheme to check for view compile errors.
This also completely bypasses checking for runtime errors that may occur. For example, lets say you change the viewmodel that a strongly-typed view is expecting. You would then update the unit test to make sure that the Controller.Action()
is returning a view result with the correct view model type, but that does nothing to make sure that the actual view was updated correctly for the new view, and yet this scenario will cause a run-time exception. This is an easy scenario to occur, especially since if the differences in the two view models are only seen in partials used within the view.
Other examples of code that can cause runtime exceptions in views are incorrect loops (possibly caused by changes in a view model), code that checks a user's role (so buttons are only shown for users with credentials), incorrect casts (e.g. for converting a collection into a select list), incorrect code to sort a collection (how a collection is sorted in the display can construed as a view concern, not a controller or view model concern), if strings used for locations of files don't work correctly (T4MVC doesn't integrate well with some things, such as Telerik's script registration system) etc...
The way I see it, there are many things that can cause an exception to occur in the process of rendering a view, and I can't seem to find any way to create unit or integration tests to determine when these occur. I would feel more comfortable if I did not have to check every page to make sure I missed a compile time or runtime error for something that a standard unit test should be able to catch.
What options do I have to do this?
I would prefer to stay away from WaTiN and other GUI testing tools, as for this I am not interested in the actual display of the page, I only want to know if the view renders or if an exception occurs and do not need the overhead of Watin running an IE instance for each test (I also think this will cause issues if I go with continuous integration at a later point).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您不想使用 WaTIN 和 IE,可以在 IIS Express 中启动您的网站,然后对每个视图的 URL 使用
HttpWebRequest
来检查结果是否为 200 OK。这是一个完整的集成测试。否则,您必须从控制器获取
ViewResult
,并调用ExecuteResult
方法,传入包含存根HttpContextBase< 的
ControllerContext
。 /代码>。这提供了更多真正的单元测试,并且速度更快,但是在它起作用之前你需要做很多模拟和存根工作。If you don't want to use WaTIN and IE, how about firing up your web site in IIS Express, and then using
HttpWebRequest
over each of your Views' urls to check the result is 200 OK. This is a complete integration test.Otherwise, you have to get the
ViewResult
from your controller, and call theExecuteResult
method passing in aControllerContext
containing a stubbedHttpContextBase
. This gives more of a true unit test, and would be faster, but you've got a lot of mocking and stubbing to do before it will work.mspec mvc 扩展
mspec mvc extensions