这是我很长时间以来处理过的最令人困惑的事情。我有一个控制器操作,当发表评论时会发送一封电子邮件:
class CommentsController < ActionController::Base
def create
@comment = Comment.new(params[:comment])
@comment.author = current_user
@comment.save
CommentMailer.recent_comment_made(@comment).deliver
respond_with(@comment)
end
end
我想测试一下。我的测试转到正确的页面(我已经验证了这一点),其中有一个带有操作/评论的表单。然后它提交表单并使用成功的 Flash 返回视图(使用 FlashResponder),一切似乎都很好……但电子邮件从未发送过。事实上,整个 create 动作都不会被调用。奇怪的是,同样的过程在开发中起作用,但发送电子邮件!
现在我知道它到达了正确的控制器,因为我可以添加这个:
before_filter { raise }
并且测试失败。我可以补充:
before_filter { p params }
我看到参数,其中控制器为“评论”,操作为“创建”。但如果我添加:
def create
raise
...
没有引发异常。事实上,我可以只注释掉整个 create 方法,测试仍然通过,注释被创建和一切。我没有使用 InheritedResources 或任何类似的东西。就像我说的......它适用于开发!
我save_and_open_page
在每一步之后都使用过,一切看起来都很好。表单操作是正确的。闪现消息是正确的。创建注释的断言是正确的......即使创建方法被完全注释掉。
最初我认为这是错误的控制器,或者 Cucumber 出于某种未知原因使用了我的控制器的某些旧版本,但是当我添加 before_filters 以提高/打印参数时......这一切都会发生并按预期工作。
有谁知道这里会发生什么,或者我至少可以看到这里发生了什么?我完全没有想法。我的功能如下所示:
Given I visit the page
And I enter a comment
When I submit the comment
Then the e-mail is delivered
And the comment is saved to the database
这些比实际更通用,以隐藏项目的实际意图。步骤定义伪代码为:
visit ...
fill_in ...
find('submit button').click
assert ActionMailer::Base.deliveries.include? ...
assert comments.present?
很简单的东西。访问页面,提交表单,断言创建操作中的内容有效。