Ruby-on-rails 如何在 Rails 中使用 Rspec 存根错误?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14942828/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:25:13  来源:igfitidea点击:

How to stub error raising using Rspec in Rails?

ruby-on-railsrubyunit-testingrspecstubbing

提问by Marina K

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

我是 Rails 和 Rspec 的新手,我正在使用 Rspec 来测试这个控制器方法,其中包括异常处理:

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

运行后测试失败并出现错误: 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:

正如 nzifnab 解释的那样,它无法找到Movie::NoDirectorError. 我忘了定义这个异常类。所以我将它添加到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.

这解决了我的问题并且这个测试通过了。

采纳答案by nzifnab

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

该错误表明它不知道该Movie::NoDirectorError异常类的定义位置。您可能需要专门require定义该类的文件,否则测试可能无法找到它。

Rails will automatically attempt to locate any constant missingconstants using a conventional file directory format. It will look for a file in the load_pathat movie/no_director_errorand moviebased 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.

Rails 会自动尝试constant missing使用传统的文件目录格式定位任何常量。它会寻找在一个文件中load_pathmovie/no_director_error,并movie基于常量的名称。如果未找到该文件或该文件未定义预期的常量,则您需要自己专门要求该文件。

回答by Philip Hallstrom

You're very close. You need to add any_instancein there.

你很亲近。你需要any_instance在那里添加。

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.

编辑:我误读了帖子。上面给出了一个 Movie 实例,但不适用于 OP 的问题。

回答by fkoessler

In Rails 4.1:

在 Rails 4.1 中:

verse_selector = double("VerseSelector", select_verses: ActiveRecord::RecordNotFound.new("Verses not found"))

verse_selector = double("VerseSelector", select_verses: ActiveRecord::RecordNotFound.new("Verses not found"))

verse_selector.select_verseswill now return an ActiveRecord::RecordNotFound

verse_selector.select_verses现在将返回一个 ActiveRecord::RecordNotFound