RSpec-模拟(或存根)覆盖的mixin方法 [英] RSpec - mock (or stub) overriden mixin method

查看:66
本文介绍了RSpec-模拟(或存根)覆盖的mixin方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的情景:

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

现在问题出在测试上-我想确保从重写的方法中调用了super方法并将其存根,以便我可以测试方法的其他部分.如何使用RSpec模拟来完成?

Now the problem is with testing - I would like to ensure that super method got called from overriden method and stub it so that I can test other parts of method. How can I accomplish that using RSpec mocks?

推荐答案

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

Ensuring that super gets called sounds a lot like testing the implementation, not the behaviour, and mocking the subject-under-test isn't such a great idea anyway. I would suggest just explicitly specifying the different code paths

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

  it "returns :some_symbol when not xxx" do
    ...
  end
end

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

If you had a lot of classes that included that module, you could use shared examples to reduce the duplication in your tests.

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调用的方法它.

Update: If you really can't predict the behaviour of the mixin, you could switch out what method gets called by super by including another module that defines it.

如果您的类C包含均定义方法f的模块MN,则在C#f中,super将引用最后一个包含的模块.

If you have a class C that includes modules M and N that both define a method f, then in C#f, super will refer to whichever module was included last.

class C
  include M
  include N

  def f
    super # calls N.f because it was included last
  end
end

如果将其包含在被测对象的单例课程中,则不会影响其他任何测试:

If you include it in the singleton class of your subject-under-test, then it won't affect any other tests:

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

免责声明:这实际上并没有测试混入是否有效,只是测试了super被调用.我仍然建议您实际测试一下行为.

Disclaimer: this doesn't actually test that the mixin works, just that super gets called. I still would advise actually testing the behaviour.

这篇关于RSpec-模拟(或存根)覆盖的mixin方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆