Probably a simple answer that’s mock or stub related but I’m newish and trying to get a better understanding of things… I’m trying to understand why test resources aren’t actually deleted? but specs pass as if they were? This may (or may not) be unique to RSpec?!?
I have a new project using RSpec and generated a scaffold for a simple Resource
$ rails new destroyer -T
...
$ rails generate rspec:install
...
$ rails g scaffold resource name:string
Everything works, as expected, and specs pass. But I’ve had some curious stuff happen and tests fail in another project so digging deeper I added some logging to my destroy method to see what’s happening:
#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
When I Destroy a resource I notice this (####) discrepancy in my logs:
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
and after running the specs I see this in 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
Why are we seeing different states (destroyed?) of a resource depending on the environment we’re running in?
If you are using the generated controller specs, you’ll see something like this for the destroy action:
The spec is not instantiating a real
Postobject, instead it is usingmock_modelto create a mock (or ‘test double’). To make it easier to test models, mocks created withmock_modelstub out some of the ActiveRecord methods, includingdestroyed?andpersisted?. As a result, these mocks won’t behave exactly the same way as real model instances.