为什么rspec测试需要一直保存和重新加载

时间:2013-06-17 13:30:42

标签: ruby-on-rails rspec

这是我的示例测试块

it 'should redirect to account portfolio items page if user is creative and its first visit is false and sign in count is 1' do 
  @creative.first_visit = false
  @creative.sign_in_count = 1
  @creative.save!
  sign_in @creative
  get :index
  @creative.reload
  @creative.first_visit.should eql(true)
  response.should redirect_to account_portfolio_items_path
end   

如果我不使用保存和重新加载测试将失败。你知道它为什么会发生,我该如何处理?

这是我的测试宝石。

group :test do
  gem "rspec-rails"
  gem "factory_girl"
  gem "database_cleaner"
  gem 'webrat', '0.7.1'
  gem 'shoulda'
end

2 个答案:

答案 0 :(得分:0)

您应该使用assigns从RSpec中的控制器访问实例变量,而不是使用重新加载。有关编写规范的理想方式的更多详细信息,请参阅Better Specs

答案 1 :(得分:0)

听起来不错。通常,您的控制器操作会执行数据库提取以获取其数据。在您的测试中,您可能会按摩数据,但如果您不先保存,那么您的控制器将无法获得您期望的数据。想象一下这个小场景:

# in your test ...
user = User.new
get :index
assigns(:users).should eq [user]

# in your controller ...
def index
  @users = User.all
end

此测试将失败,因为测试中的user从未保存,因此当控制器执行User.all时,它无法找到用户。

与测试类似,当您更新属性并且控制器获取记录时,它不知道您的更改,因为它们尚未保存到数据库中。您肯定需要保存@creative模型。

对于重新加载,当您从数据库中获取模型或创建一个全新的模型时,它的属性存储在内存中的实例中。当您将first_visit属性更改为false时,您在内存中更改了它。保存实例时,它已应用于数据库。当您调用index操作时,它会更新所提取的Creative实例,使first_visittrue。但是,在您的测试中,您仍在使用内存中的对象,它将其作为falsereload强制从数据库中重新获取对象,这样您就可以看到它的当前和更新属性。

如果您的控制器设置了一个实例变量(如@creative),那么重新加载的替代方法是通过assigns()帮助器访问它,如下所示:

get :index
assigns(:creative).first_visit.should eql(true)

这就是说实例变量@creative(控制器设置)将first_visit属性设置为true