繁体   English   中英

如何为以下代码编写RSpec测试

[英]How to write RSpec test for the following code

我的代码功能正常运行,但是需要创建一个涵盖它的RSpec测试。 我的routes.rb:

  resources :movies do
    #member routes for individual ones
    get 'find_with_same_director', on: :member
  end
  # map '/' to be a redirect to '/movies'
  root :to => 'movies#index'

我在movies_controller.rb中的代码:

def find_with_same_director
  @movie = Movie.find(params[:id])
  @movies, check_info = Movie.find_with_same_director(params[:id])
  if check_info
    flash[:notice] = "'#{@movie.title}' has no director info"
    redirect_to movies_path
  end
end

模型movie.rb中的find_with_same_director函数:

def self.find_with_same_director(id)
  movie = self.find(id)
  if !movie.director.blank?
    movies = self.where(:director => movie.director).where.not(:id => movie.id)
    return movies, false
  else
    return [], true
  end
end

我正在尝试编写涵盖单击该函数的“查找同一导演”链接,单击的电影何时可以显示导演以及何时不显示的测试。 到目前为止,我已经为movies_controller_spec.rb编写了以下测试:

describe 'find_with_same_director' do
  it 'should call the find_with_same_director model method' do
    expect(Movie).to receive(:find_with_same_director).with(params[:id])
    get :find_with_same_director, id: movie.id
  end

  context 'movie has a director' do
    let!(:movie1) {FactoryGirl.create(:movie, :director => movie.director)}
    it do
      get :find_with_same_director, id: movie1.id
      expect(response).to redirect_to(movie_path(movie1.id))
    end
  end

  context 'movie has no director' do
    movie1 = FactoryGirl.create(:movie, :director => nil)
    it "should redirect to root" do
      get :find_with_same_director, id: movie1.id
      expect(response).to redirect_to(/movies)
    end
  end
end

我花了几个小时来进行这些测试,当我检查报告时它们正在“发现”所有行时,前两个返回失败。 这意味着我写错了。 我想修改这些测试以准确表示我的控制器代码在做什么,对此我将非常感谢。 如果您不满意,也请提供有关为模型movie.rb文件编写rspec测试代码的建议,我也将不胜感激。

隔离第一个测试时得到的错误:

  1) MoviesController find_with_same_director should call the find_with_same_director model method
     Failure/Error: expect(Movie).to receive(:find_with_same_director).with(params[:id])

     NameError:
       undefined local variable or method `params' for #<RSpec::ExampleGroups::MoviesController::FindWithSameDirector:0x000000056b27e0>

隔离第二个测试时得到的错误:

Failures:

  1) MoviesController find_with_same_director movie has a director should redirect to "/movies/28"
     Failure/Error: expect(response).to redirect_to(movie_path(movie2.id))
       Expected response to be a <redirect>, but was <200>

我有点理解为什么会发生错误,但我不知道该如何解决。

测试通常是独立进行的。 因此,让我们一个接一个地看一下它们:

您的第一个规格如下所示:

it 'should call the find_with_same_director model method' do
  expect(Movie).to receive(:find_with_same_director).with(params[:id])
  get :find_with_same_director, id: movie.id
end

重要的是要注意,在此测试的上下文中, paramsmovie都不存在,因为您确实先定义了它们。 您可能需要先制作电影来解决此问题:

let(:movie) { FactoryGirl.create(:movie) }

it 'should call the find_with_same_director model method' do
  expect(Movie).to receive(:find_with_same_director).with(movie.id)
  get :find_with_same_director, id: movie.id
end

两个建议:

  1. FactoryGirl被淘汰是有充分理由的 它由FactoryBot代替。 请更新。
  2. IMO完全不应该存在此规范,因为它测试了内部实现细节。 测试应具体说明方法返回的内容或该方法产生的副作用。 但是测试不应该测试如何完成某件事。 原因很简单。 当您重构该方法时,即使该方法仍返回确切的似乎响应,此类测试也会中断。

您的第二个规格:

context 'movie has a director' do
  let!(:movie1) { FactoryGirl.create(:movie, :director => movie.director) }

  it do
    get :find_with_same_director, id: movie1.id
    expect(response).to redirect_to(movie_path(movie1.id))
  end
end

该规范有两个问题。 似乎您假设要找到类似的电影并重定向到该电影。 但是,您只能创建一部电影,没有其他电影可以重定向到。 而且即使它已经存在,控制器中也没有重定向,并且由于您的方法返回了多个影片,因此不清楚要重定向到哪些相似的影片。

您的第三个规格不能正确制作电影。 一旦解决此问题,我认为规格将通过。

context 'movie has no director' do
  let(:movie) { FactoryGirl.create(:movie, :director => nil) } # <= this creates the movie for the test

  it "should redirect to root" do
    get :find_with_same_director, id: movie.id
    expect(response).to redirect_to(/movies)
  end
end

此外,我建议用范围替换find_with_same_director并查看find_with_same_director的文档-特别是控制器规范的工作方式以及letlet!之间的区别let!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM