Reputation: 3029
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:
@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 [email protected]?
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
Upvotes: 1
Views: 1699
Reputation: 2228
I can tell you why the database call is happening in the first place.
You should replace this line:
Product.stub!(:create).and_return(@product)
with:
Product.any_instance.stub!(:save).and_return(true)
You are stubbing the class method Product::create
, but you really need to stub the instance method Product#save
.
I suppose the following would also work:
Product.stub!(:new).and_return(@product)
@product.stub(:save).and_return(true)
Because of the failure to save
you go through the render
path 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.
Upvotes: 1