如何跳过 Rails 规范中的部分方法代码

How to skip part of method code in Rails specs

我有这个方法

def finalize_inquiry_process(form)
  if finalize_process == true
    inquiry_process.campaign_code.update(state: 'used')
    document_creator_class = InquiryProcessDocumentCreatorFetcher.new(inquiry_process).call
    document_creator_class.new(inquiry_process).call
  end
  Success(form)
end

我想在规范中跳过这部分,这真的很麻烦,实施是不必要的浪费时间(具有大量字段的 pdf 生成器)

document_creator_class = InquiryProcessDocumentCreatorFetcher.new(inquiry_process).call
document_creator_class.new(inquiry_process).call

为此我写了一个规范:

  let(:fetcher_instance) { instance_double(InquiryProcessDocumentCreatorFetcher) }

  before do
    allow(InquiryProcessDocumentCreatorFetcher).to receive(:new).and_return(fetcher_instance)
    allow(fetcher_instance).to receive(:call).and_return(nil)
  end

  it 'updates state of assigned campain code' do
    updated_inquiry_process = process_update.value!
    expect(updated_inquiry_process.campaign_code.state).to eq('used')
  end
end

InquiryProcesses::Update.call campain code updates state of assigned campain code Failure/Error: document_creator_class.new(inquiry_process).call

NoMethodError: undefined method `new' for nil:NilClass

是否有机会在规范中跳过这部分代码?

好的,我使用 receive_message_chain 助手来管理它。规格应如下所示:

describe 'finalize inquiry process' do
  subject(:process_update) do
    described_class.new(
      inquiry_process: inquiry_process,
      form: loan_application_inquiry_process_update_form,
      finalize_process: true,
    ).call
  end

  let!(:inquiry_process) do
    create :inquiry_process, inquiry_template: loan_inquiry_template, campaign_code_uid: campaign_code.uid
  end

  before do
    allow(InquiryProcessDocumentCreatorFetcher).to receive_message_chain(:new, :call, :new, :call)
  end

  it 'updates state of assigned campain code' do
    updated_inquiry_process = process_update.value!
    expect(updated_inquiry_process.campaign_code.state).to eq('used')
  end
end

你可以试试依赖注入的运气: (粗略的勾勒了一下,不知道系统的上下文,连整个都不知道class)

def initialize(inquiry_process:, form:, finalize_process:,  creator_fetcher:) 
  @creator_fetcher = creator_fetcher
  # all the other initializetions
  # maybe you can initialize creator_fetcher outside, and no need to pass inquiry_process anymore?
end

def creator_fetcher
  @creator_fetcher ||= InquiryProcessDocumentCreatorFetcher.new(inquiry_process)
end

def finalize_inquiry_process(form)
  if finalize_process == true
    inquiry_process.campaign_code.update(state: 'used')
    document_creator_class = creator_fetcher.call
    document_creator_class.new(inquiry_process).call
  end
  Success(form)
end

然后是

let(:creator_fetcher) { instance_double(InquiryProcessDocumentCreatorFetcher) }
let(:document_creator_class) { instance_double(whatever_fetcher_call_returns_or_just_unveryfying_double) }

before { allow(creator_fetcher.to_receive(:call).and_return(document_creator_class) }

subject(:process_update) do
  described_class.new(
    inquiry_process: inquiry_process,
    form: loan_application_inquiry_process_update_form,
    finalize_process: true,
  ).call
end

无论如何 - 你的测试问题表明你的代码不是用测试编写的,这是一个糟糕的设计。

间接(此处为依赖注入)可能有助于理清混乱局面。