【发布时间】:2015-04-28 00:27:58
【问题描述】:
我正在为 Rails 编写一个 gem,其中包括一个用于创建模型的生成器。在某些情况下,生成器应该调用自己,它使用generate 方法来执行此操作。实际使用时效果很好。
我正在使用带有generator_spec 的 RSpec 3.2 来尝试测试此功能,但作为一个 gem,当它到达 generate 调用时,它抱怨 Rails 不存在:
/path/to/ruby: No such file or directory -- bin/rails (LoadError)
所以我一直在尝试对Generator#generate 方法进行存根,使其在规范中与run_generator 执行相同的操作,紧接在它们中间调用generate 的run_generator 调用之前。
但是,对于我所有可能的解决方案,我都遇到了问题。
直接覆盖类 - 不能使用规范方法。
class Generator
def generate(*args)
run_generator args[1..-1]
end
end
这引发了undefined method 'run_generator'。不足为奇。
使用部分双精度实例化太晚了。
allow(generator).to receive(:generate) { |*args| run_generator args[1..-1] }
这将是完美的,但 run_generator 在后台调用了一个 class 方法,因此所讨论的 generator 尚不存在。
使用实例 double - 不允许使用其他方法。
recursible = instance_double(Generator)
allow(recursible).to receive(:generate) { |*args| run_generator args[1..-1] }
test_case_instance.generator_class = recursible
但是,使用 double 需要您将要使用的方法存根 所有 - 而所有其他方法都只是调用它们的原始实现。这似乎是困难和不必要的。有什么办法可以绕过去吗?
【问题讨论】:
-
你试过了吗:
allow_any_instance_of(Generator).to receive(:generate) ... -
@TarynEast 有前途!但现在我收到了
rspec __generate_without_any_instance__ takes -2 argument, but it should not. -
好的,所以存根应该完全覆盖一个方法并用简单的返回值替换它......当你传递正确的参数时......这意味着你确实需要将参数传递给它(在这种情况下,我只是用
...抽象多佛尔,但你应该有类似.with(arg1, arg2)的东西(无论你期望的参数是什么)然后你应该返回一个返回值......但是......如果你实际上是在尝试在存根中运行代码......那么你可能将它用于错误的目的......并且可能还有另一种方式你应该这样做。 -
您是否在 Google 上搜索过有关如何测试作为 rails gem 的 gem 的教程?我认为他们倾向于在测试目录中包含完整的迷你应用程序......
-
我感觉
run_generator实际上调用generate在链条的某个地方,不知何故...