可能是一个简单的答案,模拟或存根相关,但我是新的,并试图更好地理解事物......我试图理解为什么测试资源实际上不是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?
)?
答案 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中看到的相同结果。