0

I am new to testing. I don't seem to be able to account for a variable in my controller in my rspec tests. How can I account for the needed variable in my tests and make these tests pass?

Current test:

describe "POST create action" do
    let(:trip)              { create(:trip)}
    let(:trip_date)         { create(:trip_date) }
    let(:buyer)             { create(:buyer) }
    let(:company)           { create(:company) }
    let(:order_item)        { attributes_for(:order_item, trip_date_id: trip_date.id, buyer_id: buyer.id, company_id: company.id) }
    let(:bad_order_item)    { attributes_for(:bad_order_item, trip_date_id: trip_date.id, buyer_id: buyer.id, company_id: company.id) }

    context "given valid order item attributes" do
        it "creates a new order item" do
            expect{ post :create, order_item: order_item, trip_id: trip.id }.to change(OrderItem, :count).by(1)
        end
    end
end

This is my error message:

OrderItemsController POST create with valid attributes creates a new order item
Failure/Error: expect{ post :create, order_item: FactoryGirl.attributes_for(:order_item) }.to change(OrderItem,:count).by(1)
NoMethodError:
       undefined method `company_id' for nil:NilClass
 # ./app/controllers/order_items_controller.rb:29:in `create'
 # ./spec/controllers/order_items_controller_spec.rb:47:in `block (4 levels) in <top (required)>'

Error references line 29 of my order_items_controller.rb:

line 25:    def create
line 26:        @trip = Trip.friendly.find_by_id(params[:trip_id)
line 27:        @order_item = OrderItem.new(order_item_params)
line 28:        @order_item.buyer_id            = current_user.id
line 29:        @order_item.company_id          = @trip.company_id
line 30:        @order_item.first_person_cost   = @trip.first_person_cost
line 31:        @order_item.second_person_cost  = @trip.second_person_cost

line 32:        if @order_item.save
line 33:            redirect_to cart_path(current_user), notice: 'New order item created.'
line 34:        else
line 35:            render 'new', notice: 'Unable to create new order item.'
line 36:        end    
line 37:    end  

The only callback affecting this controller action confirms the user is signed in before the action begins. If they are not, they are redirected to the sign in page.

I have also tried: let(:trip) { create(:trip)} let(:trip_date) { create(:trip_date) } let(:buyer) { create(:buyer) } let(:company) { create(:company) } let(:order_item) { attributes_for(:order_item, trip_date_id: trip_date.id, buyer_id: buyer.id, company_id: company.id) } let(:bad_order_item) { attributes_for(:bad_order_item, trip_date_id: trip_date.id, buyer_id: buyer.id, company_id: company.id) }

describe "POST create" do
    let(:trip)     {create(:trip) }
    context "with valid attributes" do
        it "creates a new order item" do
          Trip.stub_chain(:friendly, :find_by_id).and_return(trip)
          expect{ post :create, order_item: order_item }.to change(OrderItem,:count).by(1)
          end
      end
    end
end

Resulting in an error of:

1) OrderItemsController POST create action given valid order item attributes creates a new order item
    Failure/Error: let(:trip)               { create(:trip)}
    Double received unexpected message :where with (no args)
        # ./spec/controllers/order_items_controller_spec.rb:34:in `block (3 levels) in <top (required)>'

Additionally, documentation on specific Rpsec code can be hard to find. I'd especially appreciate being pointed in the right direction toward the docs for rspec's 'post' method.

Thanks in advance.

1 Answer 1

1

You can't assign some variables in spec and get them in controller!

There are several ways how to test it

1 Controller finds record in DB - so create it that Trip.friendly.find_by_id(params[:trip_id) return it

describe "POST create" do
  let(:trip) { FactoryGirl.create(:trip) }

  context "with valid attributes" do
    it "creates a new order item" do
      order_item = FactoryGirl.attributes_for(:order_item)
      expect{ post :create, order_item: order_item, trip_id: trip.id }.to change(OrderItem,:count).by(1)
    end
  end
end 

2 Use stub (or stub_chain)

describe "POST create" do
  let(:trip) { FactoryGirl.create(:trip) }
  context "with valid attributes" do
    it "creates a new order item" do
      Trip.stub_chain(:friendly, :find_by_id).and_return(trip)
      order_item = FactoryGirl.attributes_for(:order_item)
      expect{ post :create, order_item: order_item }.to change(OrderItem,:count).by(1)
    end
  end
end

PS As for me first variant is better, because controller really accept params[:trip_id] so it is better to pass it.

Sign up to request clarification or add additional context in comments.

9 Comments

These methods have both started failing again. Same error message. When I attempt the second example you suggest, it returns "Double received unexpected message :where with (no args)". No other tests have started failing, just this one.
You should choose a strategy for testing: stubbing some queries or create real data (I prefer create real data for controller tests). According to the error you use double which receive "unexpected" method where. In your posted code I don't see no where in controller no double in tests. Post you controller and spec code.
I've updated the code that was working at first, but now is failing.
I don't understand what is going: you created a new question (it is ok) where posted the same code but error is undefined method company_id' for nil:NilClass`. Here you said that the problem is " "Double received unexpected message :where". Also you did not post all action code where you get error. Please clarify all these things
I have received both error messages. I've updated this question to clarify which attempt results in which error message, and deleted my new question.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.