任何实例

rspec-mocks 提供了两种方法,allow_any_instance_ofexpect_any_instance_of,它们允许你存根或模拟类的任何实例。它们用于代替 allowexpect

  allow_any_instance_of(Widget).to receive(:name).and_return("Wibble")
  expect_any_instance_of(Widget).to receive(:name).and_return("Wobble")

这些方法将适当的存根或期望添加到 Widget 的所有实例。

你也可以以相同的方式 配置响应

此功能在处理遗留代码时有时很有用,但总的来说,我们出于多种原因不鼓励使用它。

使用 allow_any_instance_of 存根方法

给定一个名为“example_spec.rb”的文件,其中包含

RSpec.describe "allow_any_instance_of" do
  it "returns the specified value on any instance of the class" do
    allow_any_instance_of(Object).to receive(:foo).and_return(:return_value)

    o = Object.new
    expect(o.foo).to eq(:return_value)
  end
end

我运行 rspec example_spec.rb

那么所有示例都应该通过。

使用 allow_any_instance_of 存根多个方法

给定一个名为“example_spec.rb”的文件,其中包含

RSpec.describe "allow_any_instance_of" do
  context "with receive_messages" do
    it "stubs multiple methods" do
      allow_any_instance_of(Object).to receive_messages(:foo => 'foo', :bar => 'bar')

      o = Object.new
      expect(o.foo).to eq('foo')
      expect(o.bar).to eq('bar')
    end
  end
end

我运行 rspec example_spec.rb

那么所有示例都应该通过。

使用特定参数存根类的任何实例

给定一个名为“example_spec.rb”的文件,其中包含

RSpec.describe "allow_any_instance_of" do
  context "with arguments" do
    it "returns the stubbed value when arguments match" do
      allow_any_instance_of(Object).to receive(:foo).with(:param_one, :param_two).and_return(:result_one)
      allow_any_instance_of(Object).to receive(:foo).with(:param_three, :param_four).and_return(:result_two)

      o = Object.new
      expect(o.foo(:param_one, :param_two)).to eq(:result_one)
      expect(o.foo(:param_three, :param_four)).to eq(:result_two)
    end
  end
end

我运行 rspec example_spec.rb

那么所有示例都应该通过。

块实现将接收器作为第一个参数传递

给定一个名为“example_spec.rb”的文件,其中包含

RSpec.describe "allow_any_instance_of" do
  it 'yields the receiver to the block implementation' do
    allow_any_instance_of(String).to receive(:slice) do |instance, start, length|
      instance[start, length]
    end

    expect('string'.slice(2, 3)).to eq('rin')
  end
end

我运行 rspec example_spec.rb

那么所有示例都应该通过。

使用 expect_any_instance_of 对任何实例设置消息期望

给定一个名为“example_spec.rb”的文件,其中包含

RSpec.describe "expect_any_instance_of" do
  before do
    expect_any_instance_of(Object).to receive(:foo)
  end

  it "passes when an instance receives the message" do
    Object.new.foo
  end

  it "fails when no instance receives the message" do
    Object.new.to_s
  end
end

我运行 rspec example_spec.rb

那么它应该失败,并显示以下输出

2 个示例,1 个失败
应该只有一个实例收到以下消息,但没有收到:foo

指定与 allow_any_instance_of 结合使用时的多个调用以获得不同的返回值

使用 allow_any_instance_of 的多调用功能会导致在每个实例上配置多调用的行为。因此,每个单独的实例将按指定顺序返回配置的返回值,然后开始重复最后一个值。

给定一个名为“multiple_calls_spec_with_allow_any_instance_of.rb”的文件,其中包含

class SomeClass
end

RSpec.describe "When the method is called multiple times on different instances with allow_any_instance_of" do
  it "demonstrates the mocked behavior on each instance individually" do
    allow_any_instance_of(SomeClass).to receive(:foo).and_return(1, 2, 3)

    first = SomeClass.new
    second = SomeClass.new
    third = SomeClass.new

    expect(first.foo).to eq(1)
    expect(second.foo).to eq(1)

    expect(first.foo).to eq(2)
    expect(second.foo).to eq(2)

    expect(first.foo).to eq(3)
    expect(first.foo).to eq(3) # repeats last value from here
    expect(second.foo).to eq(3)
    expect(second.foo).to eq(3) # repeats last value from here

    expect(third.foo).to eq(1)
    expect(third.foo).to eq(2)
    expect(third.foo).to eq(3)
    expect(third.foo).to eq(3) # repeats last value from here
  end
end

我运行 rspec multiple_calls_spec_with_allow_any_instance_of.rb

那么所有示例都应该通过。