When using factory girl and RSpec to test my controller, I’m getting the error:
Failures:
1) ProductsController Handling POST for create should redirect to products after success
Failure/Error: response.should redirect_to(products_path)
Expected response to be a <:redirect>, but was <200>
Based on the log file, it looks like the object already exists in the DB (and doesn’t meet the redirect clause in the controller), which raises two questions:
- Why aren’t the calls getting mocked/stubbed?
- What would a workaround be if I wanted to hit the DB? Using
@params = FactoryGirl.build(:product).attributes.except(:id, :created_at, :updated_at)doesn’t work either.
Any help would be awesome. Thank you.
test.log:
Processing by ProductsController#create as HTML
Parameters: {"product"=>{"name"=>"Fruit Mania", "description"=>"The mania that is taking over the planet!", "price"=>"9.99", "inventory"=>"1", "product_image"=>"#<File:0x00
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Product Exists (0.1ms) SELECT 1 AS one FROM "products" WHERE LOWER("products"."name") = LOWER('Fruit Mania') LIMIT 1
products_controller_spec.rb:
describe ProductsController, "Handling POST for create" do
def sign_in_user
user = FactoryGirl.create(:user)
sign_in user, @user
end
def do_post
post :create, :product => @params
end
before do
@product = mock_model(Product, :save=> true)
Product.stub!(:create).and_return(@product)
@params = FactoryGirl.attributes_for(:product)
end
it "should redirect to products after success" do
sign_in_user
do_post
pending "need to figure out why redirect fails"
response.should redirect_to(products_path)
end
end
Factory:
FactoryGirl.define do
factory :product do
name "Fruit Mania"
description "The mania that is taking over the planet!"
price "9.99"
inventory 1
product_image { File.open(File.join(Rails.root, 'spec', 'support', 'uploads', '1000x450.jpeg')) }
end
end
Controller:
def create
@product = Product.new(params[:product])
if !@product.valid?
flash.now[:error] = ("The product was not added: <br><li>" + @product.errors.full_messages.join("<li>")).html_safe
render "new"
else
if @product.save
redirect_to products_path, :notice => "Product created successfully!"
else
flash.now[:error] = ("There were issues adding the product to the database. Please retry")
render "new"
end
end
end
I can tell you why the database call is happening in the first place.
You should replace this line:
with:
You are stubbing the class method
Product::create, but you really need to stub the instance methodProduct#save.I suppose the following would also work:
Because of the failure to
saveyou go through therenderpath which gives an HTTP response of 200, not the 302 you were expecting.As to why it’s hitting the database, I’m afraid I can’t say why the model already exists from the given context. If you only run this single test, does it work? Try checking out this question for more ideas:
Why isn't factory_girl operating transactionally for me? – rows remain in database after tests
I hope that helps.