【问题标题】:rails - Objects persisted by FactoryGirl are not available in Controllerrails - FactoryGirl 持久化的对象在控制器中不可用
【发布时间】:2017-05-11 14:52:31
【问题描述】:

我正在 admin 命名空间中为我的控制器编写测试。使用 RSpec (3.5.0)、FactoryGirl (4.8.0)、DatabaseCleaner (1.5.3) 和 Mongoid (6.0.3)。

问题是这些测试表现得很奇怪。在测试GET index 请求时,FactoryGirl 生成的对象被成功创建并持久化。但是,控制器似乎没有找到它们。

我有三个不同的控制器。 3 人中有 2 人有此问题,而第 3 人则很有魅力。代码是一样的(除了命名),唯一的区别是工作控制器的资源是嵌套的。

配饰作品:

describe "GET #index", get: true do

    let (:accessory) { FactoryGirl.create(:accessory) }

    before do
      get :index, params: { category_id: accessory.category_id.to_s }, session: valid_session, format: :json
    end

    it "responses with OK status" do
      expect(response).to have_http_status(:success)
    end

    it "responses with a non-empty Array" do
      expect(json_body).to be_kind_of(Array)
      expect(json_body.length).to eq(1)
    end

    it "responses with JSON containing accessory" do
      expect(response.body).to be_json
      expect(json_body.first.with_indifferent_access).to match({
          id: accessory.to_param,
          name: 'Test accessory',
          description: 'This is an accessory',
          car_model: 'xv',
          model_year: '2013',
          images: be_kind_of(Array),
          category_id: accessory.category.to_param,
          dealer_id: accessory.dealer.to_param,
          url: be_kind_of(String)
        })
    end
  end

类别的那个没有:

describe "GET #index", get: true do

    let (:category) { FactoryGirl.create(:category) }

    before do
      get :index, params: {}, session: valid_session, format: :json
    end

    it "responses with OK status" do
      expect(response).to have_http_status(:success)
    end

    it "responses with a non-empty Array" do
      expect(json_body).to be_kind_of(Array)
      expect(json_body.length).to eq(1)
    end

    it "responses with JSON containing category" do
      expect(response.body).to be_json
      expect(json_body.first.with_indifferent_access).to match({
          id: category.to_param,
          name: 'Test category',
          image: be_kind_of(String),
          url: be_kind_of(String)
        })
    end
  end

如您所见,逻辑是相同的:在before 钩子中发出请求并使用let 设置对象。

另外一个奇怪的地方是GET show 对具有相同逻辑的类别进行测试完美地工作。

在这些问题(12)中,他们说这可能是由于 DatabaseCleaner 策略,应该使用 truncation 而不是 transaction 策略。我这样做是因为 Mongoid 只允许 truncation。而且我也没有使用支持 JavaScript 的测试,并专门告诉 rspec 给use_transactional_fixtures = false

FactoryGirl 和 DatabaseCleaner 的 RSpec 配置:

RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods

  config.before(:suite) do
    DatabaseCleaner.strategy = :truncation
    DatabaseCleaner.clean_with(:truncation)
  end

  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

我可以通过在每个示例中发出请求并创建一个对象来使这些测试通过,而不是使用beforelet。但我认为它应该适用于他们。

控制器索引方法是默认的:

def index
  @thing = Thing.all
end

你对这种奇怪的行为有什么想法吗?

【问题讨论】:

    标签: ruby-on-rails rspec mongoid factory-bot database-cleaner


    【解决方案1】:

    请尝试let! 而不是let

    请注意,let 是惰性求值的。当您调用category.to_param 时会生成类别数据。它不存在于before 块中。

    另见https://relishapp.com/rspec/rspec-core/v/3-5/docs/helper-methods/let-and-let

    【讨论】:

    • 哦,对了!不敢相信我没有注意到我实际上是在工作示例中调用该对象。非常感谢,@zaru!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-11
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    相关资源
    最近更新 更多