我已经使用 TDD 几个月了,现在我想学习如何测试我的控制器 (MVC)。
单元测试是通过测试每个功能的最小单元来进行的。有时,控制器并不小。他们从模型中获取数据,然后传递给视图。
我应该如何对控制器进行单元测试?我应该模拟控制器的依赖项吗?
控制器测试是否被视为集成测试?
谢谢你。
我已经使用 TDD 几个月了,现在我想学习如何测试我的控制器 (MVC)。
单元测试是通过测试每个功能的最小单元来进行的。有时,控制器并不小。他们从模型中获取数据,然后传递给视图。
我应该如何对控制器进行单元测试?我应该模拟控制器的依赖项吗?
控制器测试是否被视为集成测试?
谢谢你。
我做 TDD 很长时间了。我用 ASP.NET MVC 做 TDD 已经一年多了。
我从规范规则开始:“没有单元测试就没有代码行”,所以我测试了所有东西——包括控制器。控制器必须经过测试,这是 MVC 框架的目标之一 - 使这些东西可测试。
对于小型应用程序,这种方法非常有效。几乎所有的逻辑都放在控制器中,一切都经过了很好的测试。
但只要我继续使用 MVC,我就开始改变主意。我尽量让控制器保持纤薄。理想情况下,仅将调用委托给某个业务对象并包装结果。剩下的就是过滤器了。
这对我也很有效!我现在拥有单独实现/测试的业务对象,因此控制器只是集成点。没有理由测试集成点,因为它很小。
关于集成测试:我还没有遇到我真正需要的情况。不要忘记,控制器总是依赖于构造函数注入的抽象。只要您对这些抽象如何工作有“好的”假设,您就可以创建适当的单元测试。当您失败时,您只需更正单元测试。
集成测试很重要也很有用,但我尝试尽可能少地创建这些测试。
我对控制器采用与 Alexander B 相同的方法。我的控制器又薄又笨。但是,我仍然为它们编写测试,以确保它们正确调用业务或服务对象并传递正确的参数。
我上周终于发现的一个实际错误可能最好地说明了这一点。我有一个控制器,允许经理批准或拒绝来自用户的请求,它有两个视图,一个未完成请求的列表视图和一个每个请求的详细信息视图。两种视图都可以批准或拒绝。控制器调用的服务有许多其他公开的方法,包括一个用于更改请求状态的方法……您可以看到它的去向。列表视图调用正确的方法来批准或拒绝并触发工作流,详细视图只调用更改状态方法,并没有启动任何进一步的工作流。这是我的编码错误,但在我的一生中,我很久都看不到它了——工作流在后台线程中运行,我花了一周的时间在这些线程中运行,假设这是该部分中的错误。
所以对我来说
等等
要为您的控制器开发单元测试,自然的方法是模拟控制器所依赖的接口(它控制的“事物”,我们称它们为IControllable
s)。然后您可以验证控制器是否以预期的方式操作受控对象。
如果控制器和受控对象之间的交互很复杂,那么专门的集成测试可能是有意义的。例如,可能有一系列类实现IControllable
——这些实现中的每一个都能与控制器很好地协同工作吗?也许多个不同IControllables
的会交互(使用相同的资源)?或者IControllables
可能有一些棘手的方法来配置它们影响他们的行为?测试这一点的一种方法是编写一个可重用的测试套件,您可以在其中注入一系列可疑的IControllable
实现或它们的组合。
最后但同样重要的是,TDD 也是关于验收测试的。因此,在进行 TDD 时,您还将进行高级端到端测试来执行最终用户会识别的场景。最有可能的是,这些也将锻炼控制器——以这种方式也测试你的控制器和(某些)类之间的正确集成。