[英]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
重要的是要注意,在此測試的上下文中, params
和movie
都不存在,因為您確實先定義了它們。 您可能需要先制作電影來解決此問題:
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
兩個建議:
FactoryGirl
被淘汰是有充分理由的 。 它由FactoryBot
代替。 請更新。 您的第二個規格:
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
的文檔-特別是控制器規范的工作方式以及let
和let!
之間的區別let!
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.