【问题标题】:RSpec - mock (or stub) overriden mixin methodRSpec - 模拟(或存根)覆盖混合方法
【发布时间】:2013-01-10 21:33:43
【问题描述】:

我有这样的情况:

module Something
  def my_method
    return :some_symbol
  end
end

class MyClass
  include Something

  def my_method
    if xxx?
      :other_symbol
    else
      super
    end
  end
end

现在问题出在测试上——我想确保从覆盖的方法调用超级方法并将其存根,以便我可以测试方法的其他部分。如何使用 RSpec 模拟来实现这一点?

【问题讨论】:

    标签: ruby rspec mocking mixins stubbing


    【解决方案1】:

    确保super 被调用听起来很像测试实现,而不是行为,并且无论如何模拟被测对象并不是一个好主意。我建议只明确指定不同的代码路径

    describe "#my_method" do
      it "returns :other_symbol when xxx" do
        ...
      end
    
      it "returns :some_symbol when not xxx" do
        ...
      end
    end
    

    如果您有很多包含该模块的类,您可以使用共享示例来减少测试中的重复。

    shared_examples_for "Something#my_method" do
      it "returns :some_symbol" do
        expect(subject.my_method).to eq :some_symbol
      end
    end
    
    describe MyClass do
      describe "#my_method" do
        context "when xxx" do
          subject { ... }
    
          it "returns :other_symbol" do
            expect(subject.my_method).to eq :other_symbol
          end
        end
    
        context "when not xxx" do
          subject { ... }
    
          it_behaves_like "Something#my_method"
        end
      end
    end
    

    更新:如果你真的无法预测 mixin 的行为,你可以通过包含另一个模块来切换 super 调用的方法它。

    如果您有一个类 C 包含模块 MN,它们都定义了一个方法 f,那么在 C#f 中,super 将引用最后包含的模块。

    class C
      include M
      include N
    
      def f
        super # calls N.f because it was included last
      end
    end
    

    如果你将它包含在你的被测对象的单例类中,那么它不会影响任何其他测试:

    describe MyClass do
      describe "#my_method" do
        it "calls super when not xxx" do
          fake_library = Module.new do
            def my_method
              :returned_from_super
            end
          end
    
          subject.singleton_class.send :include, fake_library
    
          expect(subject.my_method).to be :returned_from_super
        end
      end
    end
    

    免责声明:这实际上并不能测试 mixin 是否有效,只是会调用 super。我仍然建议实际测试行为。

    【讨论】:

    • 问题是库支持模块,我想确保生成的对象正常工作。我不知道从 mixin 中返回了什么。
    • 我很惊讶你不知道从 mixin 中返回了什么,但无论如何我还是用一种有点老套的方法更新了我的答案。
    • 问题是MyClass实际上是一个继承自与mixin相同的插件的类。这意味着插件对我来说是一个黑匣子,我测试我的修改是否可以与库 API 一起正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2013-01-14
    • 2013-08-22
    • 2020-08-31
    • 2010-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多