Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stub error raising using Rspec in Rails?

I'm new to Rails and Rspec and I'm using Rspec to test this controller method which includes exception handling:

def search_movies_director
  @current_movie = Movie.find(params[:id])
  begin
    @movies = Movie.find_movies_director(params[:id])
  rescue Movie::NoDirectorError
    flash[:warning] = "#{@current_movie} has no director info"
    redirect_to movies_path
  end
end

I can't figure out how to correctly test the said path: after invalid search (when error is received) it should redirect to the homepage. I tried something like this:

describe MoviesController do
  describe 'Finding Movies With Same Director' do
    #some other code

    context 'after invalid search' do
      it 'should redirect to the homepage' do
        Movie.stub(:find)
        Movie.stub(:find_movies_director).and_raise(Movie::NoDirectorError)
        get :search_movies_director, {:id => '1'}
        response.should redirect_to movies_path
      end
    end

  end
end

After running the test fails with an error: NameError: uninitialized constant Movie::NoDirectorError

How to fake raising an error in this test so it actually checks whether redirect happens?

Thanks!

UPDATE:

As nzifnab explained, it couldn't locate Movie::NoDirectorError. I forgot to define this exception class. So I added it to app/models/movie.rb :

class Movie < ActiveRecord::Base
  class Movie::NoDirectorError < StandardError ; end
  #some model methods
end

This solved my problem and this test passes.

like image 381
Marina K Avatar asked Feb 18 '13 18:02

Marina K


People also ask

What is stub in RSpec?

In RSpec, a stub is often called a Method Stub, it's a special type of method that “stands in” for an existing method, or for a method that doesn't even exist yet. Here is the code from the section on RSpec Doubles − class ClassRoom def initialize(students) @students = students End def list_student_names @students.

How do you raise exceptions in Ruby?

Ruby actually gives you the power to manually raise exceptions yourself by calling Kernel#raise. This allows you to choose what type of exception to raise and even set your own error message. If you do not specify what type of exception to raise, Ruby will default to RuntimeError (a subclass of StandardError ).

How do I run RSpec with coverage?

Open coverage/index. html in your browser window to view the report. Try to get the coverage to 100% by writing RSpec tests. Every time you add a test, run rspec to see if the test is passing.


2 Answers

You're very close. You need to add any_instance in there.

Movie.any_instance.stub(:find_movies_director).and_raise(Movie::NoDirectorError)

edit: I misread the post. The above would work given an instance of Movie, but not for OP's question.

like image 94
Philip Hallstrom Avatar answered Sep 24 '22 15:09

Philip Hallstrom


The error indicates it doesn't know where that Movie::NoDirectorError exception class is defined. You might need to specifically require the file where that class is defined or the test may not be able to find it.

Rails will automatically attempt to locate any constant missing constants using a conventional file directory format. It will look for a file in the load_path at movie/no_director_error and movie based on the name of the constant. If the file is not found or the file doesn't define the expected constant than you'll need to specifically require the file yourself.

like image 32
nzifnab Avatar answered Sep 25 '22 15:09

nzifnab