ruby-on-rails 如何更改DRY规范以避免弃用警告“隐式块预期语法已弃用,您应该传递块...”

s4chpxco  于 2023-03-09  发布在  Ruby
关注(0)|答案(1)|浏览(159)

我必须遵循rspec片段:

describe "Create with a classification class added" do
  before do
    @lambda_block = lambda {
      click_button I18n.t(:button_save)
      expect(page).to have_text(I18n.t :'flash.classification_scheme.create_success')
    }     
  end   

  describe "Save should create a ClassificationScheme and a ClassificationSchemesClass" do
    subject { @lambda_block }
    it { is_expected.to change(ClassificationScheme, :count).by(1) }
    it { is_expected.to change(ClassificationSchemesClass, :count).by(1) }
  end   
end

我收到了这些弃用警告:

  • 隐式块期望语法已弃用,您应将块而不是参数传递给expect以使用提供的块期望匹配器,或者匹配器必须实现supports_value_expectations?。例如expect { value }.to change ClassificationScheme.count by 1而不是expect(value).to change ClassificationScheme.count by 1 *
  • 隐式块期望语法已弃用,您应将块而不是参数传递给expect以使用提供的块期望匹配器,或者匹配器必须实现supports_value_expectations?。例如expect { value }.to change ClassificationSchemesClass.count by 1而不是expect(value).to change ClassificationSchemesClass.count by 1 *

如果我按如下方式修改规范,那么弃用警告就会消失。expect会得到一个块而不是一个参数,无论重复了两行代码,代码都不是DRY。

describe "Create with a classification class added" do 
  it "Save should create a ClassificationScheme" do
    expect{
      click_button I18n.t(:button_save)
      expect(page).to have_text(I18n.t :'flash.classification_scheme.create_success')
    }.to change{ClassificationScheme.count}.by(1)
  end

  it "Save should create a ClassificationSchemesClass" do
    expect{
      click_button I18n.t(:button_save)
      expect(page).to have_text(I18n.t :'flash.classification_scheme.create_success')
    }.to change{ClassificationSchemesClass.count}.by(1)
  end
end

我怎样才能把lambda块传递给expect?
如果我尝试expect{@lambda_block}.to change...,则lambda块不会执行;如果我尝试expect(@lambda_block).to change...,则测试通过,但是我再次收到弃用警告。
问题是,如何将 @lambda_block 传递给 expect,同时又避免出现弃用警告。
我目前正在将一个项目从rails 5迁移到rails 6,因此当前版本:
6.0.6.1
报告规范3.12.0
导轨规格5.1.2

mcvgt66p

mcvgt66p1#

为了让你清楚地看到你拥有的东西,我把它简化了一点:

subject do
  lambda { click_button I18n.t(:button_save) }     
end
it { is_expected.to change(ClassificationScheme, :count).by(1) }

当您更改为显式块时,不再需要 lambda

subject do
  click_button I18n.t(:button_save)    
end
it { expect { subject }.to change(ClassificationScheme, :count).by(1) }
#           ^         ^
# the block is already being passed to expect, this is where your lambda used to be

当你把 lambda 放进那个块里时,这些块就变成嵌套的了,而且 lambda 永远不会被调用。你也可以通过自己调用它来修复这个问题:

subject do
  lambda { click_button I18n.t(:button_save) }     
end
it { expect { subject.call }.to change(ClassificationScheme, :count).by(1) }

如果不使用块语法{ }do endsubject将成为参数,不建议使用:

#               block has to go here vvvvvv
def expect(arg = nil, keyword: :arg, &block)
# not here ^^^  
end

可以使用ruby一元&运算符将传递的参数视为块:

subject do
  lambda { click_button I18n.t(:button_save) }     
end
it { expect(&subject).to change(ClassificationScheme, :count).by(1) }

这一点很难解释清楚:

  • 一个月一次 *

相关问题