【问题标题】:Rails Capybara Test has empty Instance VariableRails Capybara 测试有空的实例变量
【发布时间】:2013-04-24 02:55:22
【问题描述】:

我有一个控制器向我的控制器发送供应商列表,在正常视图中它工作正常。

class VendorsController < ApplicationController

  respond_to :html, :json

  def index
    @vendor_categories = VendorCategory.where(:is_top_level => true)
    @vendors = Vendor.includes(:vendor_tier, :vendor_categorizations, :vendor_categories).order('vendor_tier_id DESC, name ASC')

    respond_with @vendors
  end
end

在我看来,我有以下两行:

= debug @vendors
= debug current_user.user_vendor_choices

如果我在浏览器中查看它,它再次起作用。但是,如果我用 Capybara 和 RSpec 测试它,它是空的。

require 'spec_helper'

describe 'Vendors' do
  before do
    category = create(:vendor_category)

    5.times do 
      vendor = create(:vendor)
      vendor_categorization = create(:vendor_categorization, vendor: vendor, vendor_category: category)
      p vendor
      p category
      p vendor_categorization
    end

    visit signup_path

    @new_user = sign_up
  end

  before(:each) do
    visit destroy_user_session_path
    visit new_user_session_path
    sign_in @new_user
    visit vendors_path
  end

  it 'should save selected vendors', js: true do
    p Vendor.includes(:vendor_tier, :vendor_categorizations, :vendor_categories).order('vendor_tier_id DESC, name ASC').count
  end

end

Vendor.all 和上面的Vendor.includes... 都返回值,但由于某种原因,在我的测试中它没有显示任何内容...得到Capybara::Element not found

更新

出于测试目的,我直接使用控制器创建了 Vendors:

  def index

    @vendor_categories = VendorCategory.where(:is_top_level => true)
    4.times do
      Vendor.create({name: 'Test McTesterson', vendor_tier_id: 1})
    end
    @vendors = Vendor.includes(:vendor_tier, :vendor_categorizations, :vendor_categories).order('vendor_tier_id DESC, name ASC')

    respond_with @vendors
  end

规范通过。什么——?这一定是 FactoryGirl 问题,或者由于某种原因,我的记录在运行测试之前被删除了?在我创建对象后对它们进行安慰会显示带有 ID 的记录,我想这并不能证明它正在将它们放入数据库中......

【问题讨论】:

    标签: ruby-on-rails rspec capybara factory-bot poltergeist


    【解决方案1】:

    原来我在 spec_helper 中定义的 Database Cleaner 活动有点过于激烈。我有:

    RSpec.configure do |config|
    
      config.use_transactional_fixtures = false
    
      config.before(:suite) do
        DatabaseCleaner.strategy = :transaction
        DatabaseCleaner.clean_with(:truncation)
      end
    
      config.before(:each) do
        DatabaseCleaner.start
      end
    
      config.after(:each) do
        DatabaseCleaner.clean
      end
    
    end
    

    我不得不去掉第二个块,所以现在写着:

    RSpec.configure do |config|
    
      config.use_transactional_fixtures = false
    
      config.before(:suite) do
        DatabaseCleaner.strategy = :transaction
        DatabaseCleaner.clean_with(:truncation)
      end
    
    end
    

    而且它有效!不太清楚为什么...任何想法(除了显而易见的,在每次测试之前/之后调用数据库清理器之前)?

    【讨论】:

      【解决方案2】:

      您好,我粗略地看了一眼这个问题,不确定您是否还需要帮助,但我认为这失败的原因是您的答案只是在修补一个基本设置问题。

      当您运行 js: true 规范时(顺便说一下,js: true 应该在 describe 行,而不是 it 行),简短版本,Capybara 在不同的线程中工作,所以实例变量在 before 块中创建的,与常规 Rspec 测试不同,在规范中不可用。要使它们可用,您必须使用truncation 清理策略。

      RSpec.configure do |config|
        config.use_transactional_fixtures = false
      
        config.before(:each, js: true) do
          DatabaseCleaner.strategy = :truncation
        end
      
        config.before(:each) do
          DatabaseCleaner.start
        end
      
        config.after(:each) do
          DatabaseCleaner.clean
        end
      end
      

      TL;DR 在运行 js 测试时,基本上需要截断(除非显然您正在运行不需要任何数据库交互的 js 测试)。在运行所有其他测试时,使用事务(因为它也快得多)。我猜你的回答在某种程度上复制了这一点=)

      【讨论】:

        猜你喜欢
        • 2012-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-22
        • 2018-06-06
        相关资源
        最近更新 更多