RSpec-模拟(或存根)覆盖的mixin方法 [英] RSpec - mock (or stub) overriden mixin method
问题描述
我有这样的情景:
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
的模块M
和N
,则在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屋!