我通过创建一个扩展到库类的子类来扩展现有的库。
在子类中,我能够在initialize
方法中测试大多数功能,但无法模拟super
调用。子类看起来像下面的那样。
class Child < SomeLibrary
def initialize(arg)
validate_arg(arg)
do_something
super(arg)
end
def validate_arg(arg)
# do the validation
end
def do_something
@setup = true
end
end
如何编写rspec测试(使用mocha)以便我可以模拟super
调用?请注意,我正在initialize
类中测试Child
方法的功能。我是否必须创建单独的代码路径,在提供额外参数时不会调用super
?
答案 0 :(得分:16)
你不能模仿super
,你不应该。当您模拟某些内容时,您正在验证是否收到了特定邮件,并且super
不是邮件 - 它是关键字。
相反,如果缺少super
调用,请弄清楚此类的哪些行为会发生变化,并编写一个练习并验证该行为的示例。
答案 1 :(得分:1)
测试此方法的一个好方法是设置超类采取某些操作的期望 - 例如:
class Some::Thing < Some
def instance_method
super
end
end
和超级班:
class Some
def instance_method
another_method
end
def self.another_method # not private!
'does a thing'
end
end
现在测试:
describe '#instance_method' do
it 'appropriately triggers the super class method' do
sawm = Some::Thing.new
expect(sawm).to receive(:another_method)
sawm.instance_method
end
end
所有这一切都决定了在超级类别上调用超级
这种模式的用处取决于你如何构建你的测试/你对孩子/派生类的期望&#39;通过应用super
方法进行变异。
另外 - 密切关注class
和instance
方法,您需要相应地调整allows
和expects
YMMV
答案 2 :(得分:1)
这次聚会有点晚了,但是您也可以使用super
关键字来放弃,而要做
class Parent
def m(*args)
end
end
class Child < Parent
alias super_m m
def m(*args)
super_m(*args)
end
end
这样,您的超级方法可以像其他任何方法一样访问,并且可以例如像其他任何方法一样被存根。主要缺点是必须将参数显式传递给对super方法的调用。
答案 3 :(得分:0)
正如@myron所建议的那样,您可能想测试超级跑车中发生的行为。
但是,如果您确实想这样做,可以这样做:
expect_any_instance_of(A).to receive(:instance_method).and_call_original
假设
class B < A
def instance_method
super
end
end
class A
def instance_method
#
end
end
免责声明:expect_any_instance_of
是测试不力的标志。