1

我正在使用 rspec,并且遇到了一些问题。我在 rspec 中收到以下错误

  1) MoviesController find movies with same director should call the model method that searches for movie by director
     Failure/Error: get :samedirector, {:id => 1}
     RuntimeError:
       Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
     # ./app/controllers/movies_controller.rb:63:in `samedirector'
     # ./spec/controllers/movies_controller_spec.rb:11:in `block (3 levels) in <top (required)>'

这是我的 movies_controller_spec.rb

describe MoviesController do  
  describe 'find movies with same director' do  
    let(:movie) { Movie.create }  
    before {movie.id=1, movie.director = "Steven S", movie.title="Hello World"}  
    subject { movie }  
    it 'should call the model method that searches for movie by director' do  
      Movie.should_receive(:find).with("1")  
      #this get is passing a nil id  
      get :samedirector, {:id => movie.id}  
    end  
  end  
end  

这是我的 MovieController.rb

def samedirector  
    movie = Movie.find(params[:id])  
    @director = movie.director  
  end  

任何帮助,将不胜感激。这是一个家庭作业问题,所以如果你能给我更多的直觉并指出我做错的潜在行而不是解决方案代码,那将非常有帮助。

更新

我根据您所说的进行了修复,然后将其初始化为

before (:each) do
  @movie = Movie.create(:director => "Steven S", :title=>"Hello World")
end  

但是,我现在有以下问题。似乎没有认识到导演是控制器中的史蒂文S。不知道为什么。

4

2 回答 2

1

您正在对 nil 对象调用 .id 方法。

您在两个地方调用 .id :

before {movie.id=1, movie.director = "Steven S", movie.title="Hello World"} 

get :samedirector, {:id => movie.id}  

至少在一个地方,movie == nil。这就是您收到该错误的原因。实际上你在问 nil.id

您不应该尝试movie在两者中初始化letbefore,因为它会引起混淆。此外,局部变量不会从before子句传递到it子句,因为它们是不同的方法(因此不同的局部范围)。请改用实例变量。

相反,只使用 before 子句,并将其称为 @movie:

before(:each) do
  @movie = Movie.create(:id => 1, :director => "SS", :title => "hello")
end

it '...' do
  Movie.should_receive(:find).with("1") 
  get :samedirector, {:id => @movie.id}  
end

不过要小心创建行。如果您有 attr_accessible 或类似的东西,它实际上可能不会保存所有属性,在这种情况下您可能需要:

before(:each) do
  @movie = Movie.create
  @movie.director = "asdf"
  @movie.title = "asdf"
  @movie.save
end
于 2012-08-19T09:47:30.453 回答
0

当你这样做

Movie.should_receive(:find).with("1") 

你正在改变当你这样做时发生的事情Movie.find(1)。这取代了原始实现(即should_receive不是测试间谍)。特别是,返回值为 nil(默认情况下)。然后这会破坏您的应用程序代码,因为它不期望Movie.find返回 nil

你可以and_return用来控制应该返回什么值

Movie.should_receive(:find).with("1").and_return(movie)
于 2012-08-19T10:03:20.593 回答