簡體   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