发送变量以在请求规范

时间:2016-09-22 09:08:14

标签: ruby-on-rails rspec capybara

我正在进行第一次复杂的测试,我需要一些帮助。 我需要创建一个用户,签下他并填写表格作为他。该页面引发了错误:undefined method first_name for nil:nilClass

这两个功能都非常简单,这是测试:

it "simulates creator onboard" do
@user = FactoryGirl.create(:user)
puts @user.onboard_token.size
visit onboard_path(:token => @user.onboard_token)
puts @user.nil?
expect(@user.active).to eq(false)
click_on('step-forward')
find('input[name="user[password"]').set "12345678"
find('input[name="user[password_confirmation"]').set "12346578"
find('input[name="commit"]').click
expect(response).to redirect_to(root_path)
expect(@user.active).to eq(true)

这是控制器功能:

 def onboard
authorize(:user, :onboard?)
if params[:token].present?
  if params[:token] != nil && params[:token].size == 40 && !User.where(onboard_token: params[:token]).empty?
     @user = User.find_by_onboard_token(params[:token])
  end
  if !@user.nil?
    sign_in(:user, @user)
    @brand = @user.profile
    sign_out(:user)
  end
else
  sign_out(:user)
  redirect_to root_path
end

出于某种原因,似乎@user变量未传递给视图。我确定它不是零,确保使用正确的capybara函数,但仍然,@ user是nil。

我错过了什么吗?

1 个答案:

答案 0 :(得分:0)

由于您将Selenium与Capybara一起使用,因此该测试存在许多问题

  1. 如果您正在使用事务性测试,那么在测试线程中创建的对象在应用程序线程中不可见 - https://github.com/jnicklas/capybara#transactions-and-database-setup
  2. Capybara中的操作是异步的,因此尝试在触发操作后立即测试对象上的值(对显示的内容没有任何预期以确保操作已完成)将是不稳定的
  3. 您不能同时使用visit和'回复'
  4. present?的对象不能为零
  5. 如果有令牌但没有用户匹配,您的代码仍会尝试呈现视图但没有@user且没有@brand
  6. 要解决这些问题,您需要设置DatabaseCleaner之类的内容,并确保使用截断或删除策略进行使用selenium驱动程序的测试。这将允许在测试线程中创建的对象在应用程序中可见(在您的情况下是用户)。那么你的测试应该更像是

    it "simulates creator onboard" do
      @user = FactoryGirl.create(:user)
      visit onboard_path(:token => @user.onboard_token)
      #You need to expect for something that should be on the screen before checking user.active - since this can occur before the visit has actually done anything
      #expect(@user.reload.active).to eq(false)
      click_on('step-forward')
      find('input[name="user[password"]').set "12345678"
      find('input[name="user[password_confirmation"]').set "12346578"
      find('input[name="commit"]').click
      expect(page).to have_current_path(root_path)
      expect(@user.reload.active).to eq(true)
    end
    

    控制器更像

    def onboard
      authorize(:user, :onboard?)
      if params[:token].present? && params[:token].size == 40
        @user = User.find_by_onboard_token(params[:token])
        if !@user.nil?
         sign_in(:user, @user)
         @brand = @user.profile
         sign_out(:user)
        else
         # do something here because it means the token was invalid
        end
      else
        sign_out(:user)
        redirect_to root_path
      end