【问题标题】:Negating a custom RSpec matcher that contains expectations否定包含期望的自定义​​ RSpec 匹配器
【发布时间】:2018-08-07 11:34:51
【问题描述】:

我有一个自定义的 RSpec 匹配器,用于检查作业是否已安排。它是这样使用的:

expect { subject }.to schedule_job(TestJob)

schedule_job.rb:

class ScheduleJob
  include RSpec::Mocks::ExampleMethods

  def initialize(job_class)
     @job_class = job_class
  end

  ...

 def matches?(proc)
   job = double
   expect(job_class).to receive(:new).and_return job
   expect(Delayed::Job).to receive(:enqueue).with(job)
   proc.call
   true
 end

这适用于正匹配。但它不适用于负匹配。例如:

expect { subject }.not_to schedule_job(TestJob) #does not work

为了使上述工作正常,matches? 方法需要在未满足期望时返回 false。问题是,即使它返回 false,也已经创建了期望值,因此测试错误地失败了。

关于如何制作这样的东西有什么想法吗?

【问题讨论】:

  • 您说does not work 时并不准确。当matches? 失败时,AFAIR 否定匹配器将通过。因此,如果您对matches? 的至少一个期望失败了,则它是yes 的否定版本。这是你正在得到的行为吗?如果你想要别的东西 - 请更新你的问题。
  • 如果matches? 方法本身的期望设置失败,我认为说matches? 返回错误是不正确的。否定匹配器不起作用,因为当代码没有安排作业时,预期会失败,例如expect(job_class).to receive(:new).and_return job 失败

标签: ruby-on-rails rspec rspec-rails rspec3


【解决方案1】:

我不得不寻找它,但我认为它在rspec documentation 中有很好的描述

使用expect.not_to 时的单独逻辑的格式(来自文档):

RSpec::Matchers.define :contain do |*expected|
  match do |actual|
    expected.all? { |e| actual.include?(e) }
  end

  match_when_negated do |actual|
    expected.none? { |e| actual.include?(e) }
  end
end

RSpec.describe [1, 2, 3] do
  it { is_expected.to contain(1, 2) }
  it { is_expected.not_to contain(4, 5, 6) }

  # deliberate failures
  it { is_expected.to contain(1, 4) }
  it { is_expected.not_to contain(1, 4) }
end

【讨论】:

  • Stackoverflow 往往不赞成那些只链接到其他地方的答案。我为您添加了实际答案,但您下次知道... :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多