zasman
zasman

Reputation: 486

Rspec: Creating user before testing method

Hi I am new to rspec (and unit testing in general) and want to test the following method:

class HelloController < ApplicationController

  def hello_world
    user = User.find(4)
    @subscription = 10.00
    render :text => "Done."
  end
end

I am trying to use Rspec like so:

Describe HelloController, :type => :controller do

    describe "get hello_world" do

      it "should render the text 'done'" do
        get :hello_world
        expect(response.body).to include_text("Done.")
      end
    end
  end

I would like to simply test that the method works properly and renders the test "done". I get the following error when I run the test:

 Failure/Error: user = User.find(4)

 ActiveRecord::RecordNotFound:
   Couldn't find User with 'id'=4

But how do I properly create a user with that id before executing it? I have tried the following based on other tutorials and questions but it doesn't work:

describe "get hello_world" do
        let(:user) {User.create(id: 4)}

            it "should render the text 'done'" do
                get :hello_world
                expect(response.body).to include_text("Done.")
            end
    end

Thank you in advance.

Upvotes: 0

Views: 4324

Answers (2)

arieljuod
arieljuod

Reputation: 15838

Do you really mean to use 'user = User.find(4)'? If you really meant to do that, you should stub the User's find method and return a user object.

it "should render the text 'done'" do
  u = User.new #a new user, your test database is empty, so there's no user with id 4
  User.stub(find: u) #stub the User's find method to return that new user
  get :hello_world
  expect(response.body).to include_text("Done.")
end

Another option is to send the user_id via params

it "should render the text 'done'" do
  u = User.create(.... your user params)
  get :hello_world, user_id: u.id
  expect(response.body).to include_text("Done.")
end

and

def hello_world
  user = User.find(params[:user_id])
  @subscription = 10.00
  render :text => "Done."
end

Anyway, I don't think you should be doing that, a hardcoded id is a bad sign. If you need to control users registrations and logins you can use something like Devise, and you may need to create an login a user before the spec.

Upvotes: 1

FBH037
FBH037

Reputation: 46

Hey so really no action (e.g. def hello_world) should rely on a specific id. So a simple alternative could be to use user = User.last or to find the user by name user = User.find_by(name: "name"). Then in the test you would create any user if you using User.last in the action.

describe "get hello_world" do
  let(:user) {User.create!}

  it "should render the text 'done'" do
    get :hello_world
    expect(response.body).to include_text("Done.")
  end
end

or if you are searching by name you can make a user with that name;

describe "get hello_world" do
  let(:user) {User.create!(name: "name")}

  it "should render the text 'done'" do
    get :hello_world
    expect(response.body).to include_text("Done.")
  end
end

Hope this helps, questions welcome.

Upvotes: 2

Related Questions