了解RSpec和Rails测试环境

时间:2011-02-16 21:05:43

标签: ruby-on-rails testing rspec

可能是一个简单的答案,模拟或存根相关,但我是新的,并试图更好地理解事物......我试图理解为什么测试资源实际上不是deleted?但规格通过好像他们一样?这可能(也可能不是)RSpec独有?!?

我有一个使用RSpec的新项目,并为简单的资源生成了一个脚手架

$ rails new destroyer -T
...
$ rails generate rspec:install
...
$ rails g scaffold resource name:string

一切正常,正如预期的那样,规格通过。但是我发生了一些奇怪的事情并且测试在另一个项目中失败了所以深入挖掘我在我的destroy方法中添加了一些日志来查看发生了什么:

#app/controllers/resources_controller.rb
def destroy
  @resource = Resource.find(params[:id])
  @resource.destroy
  logger.info "Resource Destroyed: #{@resource.destroyed?}" # <-- added
  logger.info "Persisted after destroy: #{@resource.persisted?}" # <-- added

  respond_to do |format|
    format.html { redirect_to(resources_url) }
    format.xml  { head :ok }
  end
end

当我销毁资源时,我注意到这个(####)在我的日志中存在差异:

development.log

Started POST "/resources/3" for 127.0.0.1 at 2011-02-16 12:28:25 -0800
  Processing by ResourcesController#destroy as HTML
  Parameters: {"authenticity_token"=>"87+THlPY2Ni7vQCONbeSqwfoeXI2fesc7DIj6EMSaw=", "id"=>"3"}
  Resource Load (0.2ms)  SELECT "resources".* FROM "resources" WHERE "resources"."id" = 3 LIMIT 1
  AREL (0.5ms)  DELETE FROM "resources" WHERE "resources"."id" = 3
Resource Destroyed: true               # <<<<  ###### TRUE ######
Persisted after destroy: false
Redirected to http://localhost:4002/resources
Completed 302 Found in 30ms

在运行规范之后,我在 test.log

中看到了这一点
  Processing by ResourcesController#destroy as HTML
  Parameters: {"id"=>"1"}
Resource Destroyed: false              # <<<<  ###### FALSE ######
Persisted after destroy: false
Redirected to http://test.host/resources
Completed 302 Found in 4ms

为什么我们会根据我们正在运行的环境看到资源的不同状态(destroyed?)?

2 个答案:

答案 0 :(得分:3)

如果您使用生成的控制器规范,您将看到类似于销毁操作的内容:

require 'spec_helper'

describe PostsController do

  def mock_post(stubs={})
    @mock_post ||= mock_model(Post, stubs).as_null_object
  end

  it "destroys the requested post" do
    Post.stub(:find).with("37") { mock_post }
    mock_post.should_receive(:destroy)
    delete :destroy, :id => "37"
  end
end

规范没有实例化真正的Post对象,而是使用mock_model创建模拟(或'test double')。为了更容易测试模型,使用mock_model创建的模拟会删除一些ActiveRecord方法,包括destroyed?persisted?。因此,这些模拟的行为与实际模型实例的行为完全不同。

答案 1 :(得分:0)

我不确定,但似乎合乎逻辑的是,因为每个示例都在事务内部隔离运行,所以在提交事务之前,资源不会被标记为已销毁。如果你在Cucumber场景中运行相同的东西,你可能会看到你在development.log中看到的相同结果。