在 rspec 中使用 rails 关联 - 关联方法的行为不可预测

问题描述 投票:0回答:0

问题:

当我在规范中定义一个变量然后调用关联方法时,它们似乎并不一致地查询数据库。有些似乎卡住了。如果能提供任何帮助,我将非常感激,因为我之前遇到过这个问题,并且只能通过使用

find
显式查询数据库来解决它。这似乎在不同程度上持续存在于
let
let!
before
块中。然而,它确实适用于方法定义或通过调用
find
。我的问题是我如何在这里使用
let!
语法或 rspec 提供的任何东西,而不是我的 no so pretty hack.

例如,这对

let
没有按预期工作,但与
let!
一起工作(计数意外变化):

require 'rails_helper'

RSpec.describe Form::Adaption, type: :model do
  context 'when a revision gets created' do
    let(:app) { create(:form_application, revision_counter: 1) } # NOTE: this creates an adaption
    let(:rev_adap) { create(:form_adaption, action_type: 'revision', application: app) }

    it '...' do
      doc_adap = create(:form_adaption, action_type: 'document', application: app)
      expect(doc_adap.application.revision?).to be true
      # NOTE: DB Cleaner gem destroys doc_adaption
    end

    describe '...' do
      it '...' do
        # ISSUE:
        puts "app.adaptions.count: #{app.adaptions.count}" # => 1
        puts "rev_adap.application.adaptions.count: #{rev_adap.application.adaptions.count}" # => 2
        puts "App.find(adap.id).adaptions #{Form::Application.find(rev_adap.application_id).adaptions.count}" # => 2 

        create(:form_adaption, action_type: 'document', application: app)

        # Utter Confusion: 
        puts "app.adaptions.count: #{app.adaptions.count}" # => 3
        puts "rev_adap.application.adaptions.count: #{rev_adap.application.adaptions.count}" # => 3
        puts "App.find(adap.id).adaptions #{Form::Application.find(rev_adap.application_id).adaptions.count}" # => 3 

        # ...
      end
    end
  end
end

当切换到 not 懒惰评估

let!
它确实与调试
puts
调用一起工作。

    let!(:app) { create(:form_application, revision_counter: 1) }
    let!(:rev_adap) { create(:form_adaption, action_type: 'revision', application: app) }

=> 2, 2, 2, 3, 3, 3
在上面的
puts
中。

但是我想运行的实际测试仍然失败,因为

app.adaptions
返回一个空数组,即使在
puts
上面的一行中打印计数为 4.

# i use let! to define the app and rev_adap but this also happens with regular let 

      it 'the relevant it block from above' do
        # ... 
        post_revision_doc_adap = create(:form_adaption, action_type: 'document', application: app)
        puts "Adap count: #{app.adaptions.count}" # => 4 as expected
        pp app.adaptions.first # => nil
        app.adaptions.sample(1).revision_manager
        # ISSUE: => undefined method `revision_manager' for []:Array

所以

app
似乎“卡住了”,但这会根据上下文发生变化。由于延迟加载,它不会在使用
let
定义时查询数据库以了解其相关适配的更改,但是问题甚至在其他地方的
let!
仍然存在。

通过方法调用“修复”它

当我

app
rev_adap
作为
before
块中的实例变量时,我得到相同的最终错误。 但是,当我将
app
rev_adap
定义为这样的方法时:

def app
  @__a ||= create(:form_application, revision_counter: 1)
  Form::Application.find(@__a.id)
end

def rev_adap
  @__a2 ||= create(:form_adaption, action_type: 'revision', application: app)
  Form::Adaption.find(@__a2.id)
end

并运行有问题的

it
块它确实有点工作:

# ...
doc_adap = create(:form_adaption, action_type: 'document', application: app)
# ...

pp app.adaptions # => collection witth four adaptions as expected
pp app.adaptions.sample() # => collection with one adaption ( number of adaptions after factory bot done )

但是我仍然得到与

let
顶部相同的奇怪计数行为。

我知道这不是与 rails 相关的问题,因为在 rails 控制台中定义

app
并为其创建新的
Form::Adaptions
然后将它们反映在
app.adaptions.count
中是没有问题的。我在常规应用程序的创建过程中也没有找到任何东西,而不是在查找应用程序的 FactoryBot 中。只有
save!
被调用。我没有在这里查看 Rails 内部结构。

我试着在 ActiveRecord Association Source 中四处寻找,因为我没有真正找到任何关于“rspec test rails associations”的明确内容。

我无法将这个问题这个与我的问题联系起来。第一个看起来很相似但不是很详细,第二个似乎没有关系,因为我肯定通过

create
策略坚持所有的FactoryBot用法。

测试设置:

除了 rspec 和 rspec_rails 之外,我还使用 factory_bot 和 db_cleaner gem。

Ruby 版本为 2.7.2,rails 为 6.0.6.1

Rspec 版本是: RSpec 3.12

  • rspec-core 3.12.1
  • rspec-expectations 3.12.2
  • rspec 模拟 3.12.3
  • rspec-rails 5.1.2
  • rspec 支持 3.12.0
ruby-on-rails rspec rspec-rails
© www.soinside.com 2019 - 2024. All rights reserved.