【问题标题】:Is there any RSpec expectation for any instance of a given kind?对给定类型的任何实例是否有任何 RSpec 期望?
【发布时间】:2020-04-27 17:00:03
【问题描述】:

我需要用测试覆盖我的 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】:

    我认为没有直接的方法来设置任何子类实例的期望。但是,将依赖项注入您的方法将使您更容易测试它。

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

    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)]
        expect(children.first).to receive(:my_method)
        app = App.new(children: children)
        expect(app.apply).to be true
      end
    end
    

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

    在这里,您尝试做的是挂钩 apply 方法并验证它的作用,但我们的客户端代码在测试中无法检查其中发生的事情。因此,只要对我来说这样做是有效且合理的,我就会注入我的依赖项并设定我对它们的期望。

    【讨论】:

    • 嗨,阿卜杜拉,感谢您提供如此详细的回答。我目前的解决方案与您的类似。我还在测试中迭代孩子。我希望会有更清洁的解决方案。
    • @AlexeySchepin 你不需要听到对每个子类的期望,只对其中一个子类设置期望就足够了。因此,您的测试中的一个子类实例的数组[ instance_double('SubClassA', my_method: true) ] 将足以证明所有其他子类的情况,因为my_method 方法在父类中的所有子类之间都存在,这意味着无法在一个上调用此方法其余的子类也会失败。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-23
    • 2012-02-20
    • 1970-01-01
    • 2012-10-23
    • 2023-03-24
    相关资源
    最近更新 更多