控制器测试模型出血?

时间:2011-08-05 08:39:56

标签: ruby-on-rails testing rspec mocking

我正在用RSpec编写一些测试(测试而不是规范,代码直到现在都未经测试)并且偶然发现了不确定性......

我想知道一个控制器是否正确调用模型的方法,我在可能性之间划分:

  • 使用存根模型方法测试控制器(我不知道模型方法是否实际存在或接受给定的参数)
  • 保持模型方法不被取消并且让我的控制器测试流入模型测试区域的风险(并且还使它们导致数据库访问和昂贵方法的速度变慢)
  • 编写多个控制器测试,每个控制器测试都留下未设置的模型方法(仍然很慢,但至少它很冗长)

对此有正确答案吗?

4 个答案:

答案 0 :(得分:1)

如果需要,您可以存根模型方法,但一般情况下,您不应该在控制器测试中检查模型的特定方法被调用,您应该检查控制器的响应内容。不要忘记黑匣子的比喻。

enter image description here

答案 1 :(得分:1)

我建议你测试你的控制器,而不是捣乱你的模型。当它到达数据库时,不关心测试的速度。我假设您想要对数据库进行测试,并且拥有正确的程序比测试的速度更重要,不是吗?

将功能测试视为单元测试的另一层,而不是与模型隔离的东西。您的单元测试(模型)确保某些模型方法按预期工作,然后您的控制器测试确保控制器能够使用这些方法,并且它们可以像控制器那样工作。

正如iafonov所说,不要专注于控制器测试中的模型方法。假设如果您的控制器能够给出正确的响应,那么您的模型显然可以按预期工作

当然,有些人有不同的观点。我并不认为我的建议是最好的。它对我有用,我认为它是正确的。很多人建议您应该独立于模型测试控制器,但是如何确保存根与实际实现之间没有差异?

答案 2 :(得分:1)

我参加派对的时间已经很晚了。但强烈赞同solnic并不同意Arsen7。

想一想:

  • 如果您使用的是vanilla活动记录方法,例如MyModel.find_by_id(123)您可以安全地存根,因为AR已经过良好测试,不需要他的数据库。

  • 如果您要调用在模型上定义的自定义方法,例如MyModel.foo(param1,param2)然后您仍然应该模拟/存根它,因为您应该在MyModel规范中对它进行测试。

存在模型方法的唯一缺点是,有时如果更改方法的接口,控制器将无知该更改,测试仍将通过。通常,集成或手动测试都可以发现问题。如果您正在处理一个大型项目,速度很快就会成为一个问题,并且避免与数据库交互时的性能损失是偶然的头部临时性非常值得的。

答案 3 :(得分:0)

通过良好的模型/单元测试,建议在控制器规格中存根模型(显然建议具有良好的模型/单位规格)。无论如何,请求/验收规范应涵盖完整堆栈。我喜欢将控制器规格视为控制器的“单位规格”。对于瘦的控制器,规范中的存根模型应该很容易,不应该触及任何实现细节。