RSpec: controller POST create

Rails 3.1.3 rspec-rails (2.11.4) rspec 2.11.1

I am new to rspec. I don't quite understand tests for POST create part.

I have generated scaffold, and simultaneously it generated controller_spec.rb as well.

      it "assigns a newly created plan as @plan" do         post :create, {:plan => valid_attributes}, valid_session         assigns(:plan).should be_a(Plan)         assigns(:plan).should be_persisted       end

is the default POST create test. It raises a failure, if I changed the validations of Plan

     class Plan < ActiveRecord::Base       validates :give_take, :presence => true       validates :flight_name_id, :presence => true       validates :day_departure, :presence => true       validates :weight, :presence => true     end

The failure message is

1) PlansController POST create with valid params assigns a newly created plan as @plan      Failure/Error: assigns(:plan).should be_persisted        expected persisted? to return true, got false      # ./spec/controllers/plans_controller_spec.rb:117:in `block (4 levels) in <top (required)>'

If my understanding is correct, be_persisted is testing if the newly created model instance is properly stored in DB.

I understand that my way is rather opposite: building test methods after setting actual codes. But first I need to understand RSpec.

I have also setup FactoryGirl

FactoryGirl.define do   factory :plan do     sequence(:give_take) { |n| [ 0, 1 ][n%2] }     sequence(:weight) { | n | n }     sequence(:check_in) { |c| [ true, false ][c%2] }     sequence(:flight_name_id) { |n| n }     day_departure Date.new(2012, 12, 1)   end end

which does work.

Question: Can you show me how to pass the object to create method WITH valid attributes?

Thanks in advance

soichi

Where do you define valid attributes?

Have you tried post :plan => Factory(:plan)?

On your controller, use create! to see what is preventing the save.

Where do you define valid attributes?

You mean,

   def valid_attributes      FactoryGirl.build(:plan).attributes    end

in plans_controller_spec.rb ? Even if so, I am not sure if it's a right way.

soichi

On your controller, use `create!` to see what is preventing the save.

Sorry, I don't quite understand what you mean.

my plans_controller.rb has

  def create     @plan = Plan.new(params[:plan])

    respond_to do |format|       if @plan.save         format.html { redirect_to @plan, notice: 'Plan was successfully created.' }         format.json { render json: @plan, status: :created, location: @plan }       else         format.html { render action: "new" }         format.json { render json: @plan.errors, status: :unprocessable_entity }       end     end   end

which scaffold generated by default.

What he wants to say is that you should log or print the error-array of your model and look what exactly doesn’t fit into your validations.

Hi Soichi,

You can temporarily do if @plan.save! to raise an error instead of just having it return false and not give you any feedback. Doing this is okay because you should not bother testing your validations as far as the controller is concerned (you do that on your model). In any case, try to validate your factory first (if you plan to use FactoryGirl.attributes_for) to prevent problems such as this.

You can temporarily do `if @plan.save!` to raise an error instead of just having it return false and not give you any feedback.

the same result including

    describe "with invalid params" do       ...

part failures.

Doing this is okay

In any case, try to validate your factory first (if you plan to use `FactoryGirl.attributes_for`) to prevent problems such as this.

I tried

  def valid_attributes     {       :weight => 4,       :flight_name_id => 55,       :give_take => 0,       :day_departure => "2012-12-22",       :check_in => true     }   end

In other words, running the test without FactoryGirl. But it returns

  13) PlansController POST create with valid params creates a new Plan      Failure/Error: post :create, {:plan => valid_attributes}, valid_session      ActiveRecord::RecordInvalid:        Validation failed: Give take can't be blank, Flight name can't be blank, Day departure can't be blank, Weight can't be blank

So it looks like attributes are passed properly at all. I am completely lost here...

soichi