goralph
goralph

Reputation: 1086

Stub private controller methods in Rails / RSpec

Having trouble with this simple test:

book_spec.rb

let(:books_controller) { BooksController.new }

context "GET #index" do
  it "calls Book.all" do
    Book.should_receive(:all)
    book_controller.index
  end
end

books_controller.rb

def index
  respond_with books
end

private

def books
  @books ||= Book.all
end

I want to stub out calls to ActiveRecord so that it doesn't need to interact with the DB and speeds up the tests. However I just can't seem to get this right.

Edit:

Sorry forgot the most important bit!

 Failure/Error: book_controller.index
 NoMethodError:
   undefined method `variant' for nil:NilClass

Upvotes: 0

Views: 1492

Answers (1)

Tom Kadwill
Tom Kadwill

Reputation: 1478

Testing controllers in Rails by instantiating the controller is going to be difficult. Most controller tests invoke the controller action using Rspec's get method. Try something like:

context "GET #index" do
  it "calls Book.all" do
    expect(Book).to receive(:all)
    get :index
  end
end

If you really don't want to touch ActiveRecord then you can stub Book by changing the test to something like:

let(:book) { double(:book, all: true) }

context "GET #index" do
  it "calls Book.all" do
    stub_const("Book", book) 
    expect(Book).to receive(:all)
    get :index
  end
end

However, I don't think that you are going to get much speed improvements trying to stub active record here. Loading the Rails environment, when you run your tests, is the biggest time overhead - especially for a small test suite.

Upvotes: 2

Related Questions