[英]How to write RSpec test for the following code
I have the functionality of my code working correctly, but need to create an RSpec test that covers it. 我的代码功能正常运行,但是需要创建一个涵盖它的RSpec测试。 My routes.rb:
我的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'
My code in movies_controller.rb: 我在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
The find_with_same_director function in the model, movie.rb: 模型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
I am trying to write tests that covers the click on the "Find With Same Director" link that calls the function, when the movie that was clicked has a director to show, and when it doesn't. 我正在尝试编写涵盖单击该函数的“查找同一导演”链接,单击的电影何时可以显示导演以及何时不显示的测试。 I've written the following tests in movies_controller_spec.rb for each so far:
到目前为止,我已经为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
I have spent hours working on these tests and while they are "covering" the lines when i check the report, the first two return fails. 我花了几个小时来进行这些测试,当我检查报告时它们正在“发现”所有行时,前两个返回失败。 This means I wrote them incorrectly.
这意味着我写错了。 I want to modify these tests to accurately represent what my controller code is doing and I would really appreciate some help with that.
我想修改这些测试以准确表示我的控制器代码在做什么,对此我将非常感谢。 If you're feeling down to it I would also appreciate if you gave advice on writing the rspec test code for the model movie.rb file as well.
如果您不满意,也请提供有关为模型movie.rb文件编写rspec测试代码的建议,我也将不胜感激。
The error I get when I isolate the first test: 隔离第一个测试时得到的错误:
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>
The error I get when I isolate the second test: 隔离第二个测试时得到的错误:
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>
I kind of understand why the errors are happening, I just don't know a fix for them. 我有点理解为什么会发生错误,但我不知道该如何解决。
Tests usually run in isolation. 测试通常是独立进行的。 Therefore let's look at them one after the other:
因此,让我们一个接一个地看一下它们:
Your first spec looks like this: 您的第一个规格如下所示:
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
It is important to note that in the context of this test either params
nor movie
do exist because you did define them first. 重要的是要注意,在此测试的上下文中,
params
和movie
都不存在,因为您确实先定义了它们。 You might want to fix this by creating a movie first: 您可能需要先制作电影来解决此问题:
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
Two suggestion: 两个建议:
FactoryGirl
is deprecated for a good reason . FactoryGirl
被淘汰是有充分理由的 。 It was replaced by FactoryBot
. FactoryBot
代替。 Please update it. Your second spec: 您的第二个规格:
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
This spec has two issues. 该规范有两个问题。 It seems like you assume to find a similar movie and redirect to that movie.
似乎您假设要找到类似的电影并重定向到该电影。 But you only create only one movie, there is no other movie to redirect to.
但是,您只能创建一部电影,没有其他电影可以重定向到。 And even if it was existing there is no redirect in your controller and because you method returns multiple movies it is unclear which similar movies to redirect to.
而且即使它已经存在,控制器中也没有重定向,并且由于您的方法返回了多个影片,因此不清楚要重定向到哪些相似的影片。
Your third spec doesn't create a movie correctly. 您的第三个规格不能正确制作电影。 Once that is fixed, I think the spec will pass.
一旦解决此问题,我认为规格将通过。
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
Furthermore, I suggest replacing the find_with_same_director
with a scope and have a look into the documentation of Rspec – especially how controller specs are working and the difference between let
and let!
此外,我建议用范围替换
find_with_same_director
并查看find_with_same_director
的文档-特别是控制器规范的工作方式以及let
和let!
之间的区别let!
. 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.