What is the proper way to test 'create' controller actions?
Asked Answered
H

2

12

I am using Ruby on Rails 3.2.2, Rspec 2.9.0 and RspecRails 2.9.0. I would like to test the create controller action but I don't know how to make that the "right"/"proper" way. I "scaffolded" model, controller, view, ... files, so in those files I have the common code generated by Ruby on Rails generators; in my spec file I have:

it "assigns @article" do
  new_article = FactoryGirl.build(:article)
  Article.should_receive(:new).and_return(new_article)
  post :create
  assigns[:article].should eq(new_article)
end

Maybe, (note: the above code is almost the same as that I use to test the new controller action) a better way to test create controller actions would be to pass some attribute value during the post :create action instead of proceed as I make above, but I don't know how to make that and if it is the "right"/"proper" way to make things.

So, what is the proper way to test 'create' controller actions?

Hargrove answered 11/5, 2012 at 9:22 Comment(0)
P
13

How about:

it "creates article" do 
  article_params = FactoryGirl.attributes_for(:article)
  expect { post :create, :article => article_params }.to change(Article, :count).by(1) 
end
Pinball answered 11/5, 2012 at 9:36 Comment(1)
Maybe you would say ... { post :create, :article => article_params }.to ... instead of ... { post :create, article_params }.to ....Hargrove
P
18

I'm doing it this way:

describe "#create" do
  before { post :create, { "my_model"=> { "name"=>"name" } } }
  specify("should created one my_model") { change{ MyModel.count }.from(0).to(1) }
end

Aaron Sumner who recently wrote the book Everyday Rails Testing with RSpec have an article at his blog. Where he describes it like this:

describe "POST create" do
  context "with valid attributes" do
    it "creates a new contact" do
      expect{
        post :create, contact: Factory.attributes_for(:contact)
      }.to change(Contact,:count).by(1)
    end

    it "redirects to the new contact" do
      post :create, contact: Factory.attributes_for(:contact)
      response.should redirect_to Contact.last
    end
  end

  context "with invalid attributes" do
    it "does not save the new contact" do
      expect{
        post :create, contact: Factory.attributes_for(:invalid_contact)
      }.to_not change(Contact,:count)
    end

    it "re-renders the new method" do
      post :create, contact: Factory.attributes_for(:invalid_contact)
      response.should render_template :new
    end
  end 
end
Poultice answered 11/5, 2012 at 9:45 Comment(0)
P
13

How about:

it "creates article" do 
  article_params = FactoryGirl.attributes_for(:article)
  expect { post :create, :article => article_params }.to change(Article, :count).by(1) 
end
Pinball answered 11/5, 2012 at 9:36 Comment(1)
Maybe you would say ... { post :create, :article => article_params }.to ... instead of ... { post :create, article_params }.to ....Hargrove

© 2022 - 2024 — McMap. All rights reserved.