Backo
Backo

Reputation: 18881

How to test 'new' controller actions?

I am using Ruby on Rails 3.2.2, Rspec 2.9.0 and RspecRails 2.9.0. I am trying to test a new controller action and I would like to know why I get the error explained above only for that action.

Given:

# controller
class ArticlesController < ApplicationController
  before_filter :signed_in

  def new
    @article = Article.new

    # This is just a sample code line to show you where the error happens?
    @article.new_record?

    ...
  end

  def show
    @article = Article.find(params[:id])

    ...
  end
end

# spec file
require 'spec_helper'

describe ArticlesController do
  before(:each) do
    @current_user = FactoryGirl.create(:user)

    # Signs in user so to pass the 'before_filter'
    cookies.signed[:current_user_id] = {:value => [@current_user.id, ...]}
  end

  it "article should be new" do
    article = Article.should_receive(:new).and_return(Article.new)
    get :new
    assigns[:article].should eq(article)
  end

  it "article should be shown" do
    article = FactoryGirl.create(:article)

    get :show, :id => article.id.to_s

    assigns[:article].should eq(article)
  end
end

When I run the Example related to the new action I get this error (it is related to the @article.new_record? code line in the controller file):

Failure/Error: get :new
NoMethodError:
  undefined method `new_record?' for nil:NilClass

But when I run the Example related to the show action it passes without errors.

What is the problem? How can I solve that?

Upvotes: 0

Views: 1670

Answers (2)

Frederick Cheung
Frederick Cheung

Reputation: 84172

The problem is the way you've done

Article.should_receive(:new).and_return(Article.new)

This is the same as

temp = Article.should_receive(:new)
temp.and_return(Article.new)

So by the time you are setting up the return value, Article.new has already been mocked out and so returns nil, so you're doing and_return(nil) Create the return value first, i.e.

new_article = Article.new #or any other way of creating an article - it may also be appropriate to return a mock
Article.should_receive(:new).and_return(new_article)

Upvotes: 2

oldhomemovie
oldhomemovie

Reputation: 15129

Try:

it "article should be new" do
  article = FactoryGirl.build(:article)
  Article.stub(:new).and_return(article)

  get :new

  assigns(:article).should == article
end

Upvotes: 1

Related Questions