给定种类的任何实例是否有RSpec期望?

问题描述 投票:2回答:1

我需要用测试覆盖我的Ruby on Rails代码。我使用RSpec进行测试。

有什么方法可以根据实例模拟对实例的调用? (kind_of?)。我想测试给定父类的子代是否被调用。我希望有类似allow_any_kind_of的方法,类似于allow_any_instance_of。但是我找不到类似的东西。

这是我的代码示例。我有Base个课程,还有几个孩子。在测试中,使用哪个确切的孩子并不重要。

class Parent
  def my_method; end
end
class ChildA < Parent; end
class ChildB < Parent; end

class App
  def apply  
    [ChildA.new, ChildB.new].all? { |c| c.my_method }
  end
end

我的RSpec测试。它失败是因为ChildA或ChildB都不是Parent类的实例。我可以有多个allow_any_instance_of来覆盖所有Parent的子级,但是我想保持简单,因为在实际代码中会有更多的子级。

context "#apply" do
  before do
    allow_any_instance_of(Parent).to receive(:my_method).and_return(true)
  end

  it "returns true" do
    expect(subject.apply).to be_truthy
  end
end
ruby-on-rails ruby rspec rspec-rails
1个回答
0
投票

我认为没有直接方法可以设定任何子类实例的期望。但是,将依赖项注入您的方法将使您更容易对其进行测试。

您可以用类似于以下的方式重写它:

class App
 def initialize(params_hash)
   @children = params_hash[:children] || [ChildA.new, ChildB.new]
 end

 def apply  
   children.all? { |c| c.my_method }
 end

 private

 attr_reader :children
end

然后您可以在测试中执行类似以下操作:

describe "#apply" do
  it "returns true" do
    children = 
      [
        instance_double('SubClassA', my_method: true),
        instance_double('SubClassB', my_method: true),
      ]

    children.each { |c| expect(c).to receive(:my_method) }
    app = App.new(children: children)
    expect(app.apply).to be true
  end
end

使用expect_any_instance_of可能表示代码有气味,每当我开始考虑使用它时,我都会暂停并查看我的代码,并验证是否可以用更好的方式编写它,以便于测试和依赖注入使代码易于测试。

这里您想要做的是钩在apply方法内部,并验证它的作用,但是测试中的客户代码无法检查其中的情况。因此我会在我认为合理且合理的情况下,注入依赖项并对其设置期望。

© www.soinside.com 2019 - 2024. All rights reserved.