1

I have a rails app with a cars model that takes the attribute of 'model'. I'm just trying to run a test to see if the index method in the cars controller will display all the cars. I'm not sure how to go about this. The test currently passes, but it shouldn't as I currently have an empty index method. How could I test this and what do I need to add. I've tried to read documentation with no luck. thanks

require 'rails_helper'

RSpec.describe CarsController, type: :controller do

  context "test" do
    it "displays all cars" do
      get :index
    end
  end

end
Tom
  • 1,311
  • 10
  • 18
b.herring
  • 563
  • 2
  • 18
  • @MarkMerritt For each car model to be displayed – b.herring Jan 28 '19 at 20:30
  • @MarkMerritt i understand whats happening but i didnt know where to take it from there, hence the question but thanks for your answer. – b.herring Jan 28 '19 at 20:35
  • 1
    I recommend [RSpec Controller Spec Documentation](https://relishapp.com/rspec/rspec-rails/v/3-8/docs/controller-specs) as a good place to start learning about testing. – Tom Jan 28 '19 at 21:04
  • @Tom Thanks for you suggestion. I used this and it seems to work. however my terminal said i needed to add `gem 'rails-controller-testing'` for it to work. However I didnt see this anywhere on the website unless i missed it. How come `gem 'rspec-rails'` does not suffice? – b.herring Jan 28 '19 at 22:15
  • 1
    @b.herring If you want to use `assigns` you need to also use the [rails-controller-testing gem](https://github.com/rails/rails-controller-testing). This was a structural decision made by the RSpec team. Put it in your Gemfile and you will be good to go – Tom Jan 28 '19 at 22:39

2 Answers2

1

with the current test file you have posted, your test should pass because you are doing a request to the index action and as long as there is an index action the test will pass.

require 'rails_helper'

RSpec.describe CarsController, type: :controller do

  context "test" do
    it "displays all cars" do
      get :index
    end
  end
end

However I see some people have recommended to use assigns, when using assigns to test you will need to assigns all the cars to an instance variable e.g. @cars = Cars.all or whatever records you need and also you should have your test data setup properly.

In your test you should also have some sort of list of cars to test against, e.g assuming you are using FactoryGirl/Bot: let(:cars) { create_list :car, 3 }

You test file should than look something like this:

require 'rails_helper'

RSpec.describe CarsController, type: :controller do
  let(:cars) { create_list :car, 3 }

  context "test" do
    it "displays all cars" do
      get :index
      expect(assigns(:cars)).to eq cars
    end
  end
end

Hope my answer helps.

Dillon
  • 26
  • 2
  • 6
-1

You're looking to use assigns in your controller specs. Since you don't seem to have any code yet, the fastest way to show you an example is to just run rails g scaffold car. Assuming you have rspec-rails in your Gemfile, you should get something like this in spec/controllers/cars_controller_spec.rb:

require 'rails_helper'

# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to specify the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator.  If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails.  There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.
#
# Compared to earlier versions of this generator, there is very limited use of
# stubs and message expectations in this spec.  Stubs are only used when there
# is no simpler way to get a handle on the object needed for the example.
# Message expectations are only used when there is no simpler way to specify
# that an instance is receiving a specific message.

RSpec.describe CarsController, type: :controller do

  # This should return the minimal set of attributes required to create a valid
  # Car. As you add validations to Car, be sure to
  # adjust the attributes here as well.
  let(:valid_attributes) {
    skip("Add a hash of attributes valid for your model")
  }

  let(:invalid_attributes) {
    skip("Add a hash of attributes invalid for your model")
  }

  # This should return the minimal set of values that should be in the session
  # in order to pass any filters (e.g. authentication) defined in
  # CarsController. Be sure to keep this updated too.
  let(:valid_session) { {} }

  describe "GET #index" do
    it "assigns all cars as @cars" do
      car = Car.create! valid_attributes
      get :index, params: {}, session: valid_session
      expect(assigns(:cars)).to eq([car])
    end
  end

  describe "GET #show" do
    it "assigns the requested car as @car" do
      car = Car.create! valid_attributes
      get :show, params: {id: car.to_param}, session: valid_session
      expect(assigns(:car)).to eq(car)
    end
  end

  describe "GET #new" do
    it "assigns a new car as @car" do
      get :new, params: {}, session: valid_session
      expect(assigns(:car)).to be_a_new(Car)
    end
  end

  describe "GET #edit" do
    it "assigns the requested car as @car" do
      car = Car.create! valid_attributes
      get :edit, params: {id: car.to_param}, session: valid_session
      expect(assigns(:car)).to eq(car)
    end
  end

  describe "POST #create" do
    context "with valid params" do
      it "creates a new Car" do
        expect {
          post :create, params: {car: valid_attributes}, session: valid_session
        }.to change(Car, :count).by(1)
      end

      it "assigns a newly created car as @car" do
        post :create, params: {car: valid_attributes}, session: valid_session
        expect(assigns(:car)).to be_a(Car)
        expect(assigns(:car)).to be_persisted
      end

      it "redirects to the created car" do
        post :create, params: {car: valid_attributes}, session: valid_session
        expect(response).to redirect_to(Car.last)
      end
    end

    context "with invalid params" do
      it "assigns a newly created but unsaved car as @car" do
        post :create, params: {car: invalid_attributes}, session: valid_session
        expect(assigns(:car)).to be_a_new(Car)
      end

      it "re-renders the 'new' template" do
        post :create, params: {car: invalid_attributes}, session: valid_session
        expect(response).to render_template("new")
      end
    end
  end

  describe "PUT #update" do
    context "with valid params" do
      let(:new_attributes) {
        skip("Add a hash of attributes valid for your model")
      }

      it "updates the requested car" do
        car = Car.create! valid_attributes
        put :update, params: {id: car.to_param, car: new_attributes}, session: valid_session
        car.reload
        skip("Add assertions for updated state")
      end

      it "assigns the requested car as @car" do
        car = Car.create! valid_attributes
        put :update, params: {id: car.to_param, car: valid_attributes}, session: valid_session
        expect(assigns(:car)).to eq(car)
      end

      it "redirects to the car" do
        car = Car.create! valid_attributes
        put :update, params: {id: car.to_param, car: valid_attributes}, session: valid_session
        expect(response).to redirect_to(car)
      end
    end

    context "with invalid params" do
      it "assigns the car as @car" do
        car = Car.create! valid_attributes
        put :update, params: {id: car.to_param, car: invalid_attributes}, session: valid_session
        expect(assigns(:car)).to eq(car)
      end

      it "re-renders the 'edit' template" do
        car = Car.create! valid_attributes
        put :update, params: {id: car.to_param, car: invalid_attributes}, session: valid_session
        expect(response).to render_template("edit")
      end
    end
  end

  describe "DELETE #destroy" do
    it "destroys the requested car" do
      car = Car.create! valid_attributes
      expect {
        delete :destroy, params: {id: car.to_param}, session: valid_session
      }.to change(Car, :count).by(-1)
    end

    it "redirects to the cars list" do
      car = Car.create! valid_attributes
      delete :destroy, params: {id: car.to_param}, session: valid_session
      expect(response).to redirect_to(cars_url)
    end
  end

end
danielricecodes
  • 3,446
  • 21
  • 23