Minitest存根将块传递给模拟实例

时间:2018-07-12 17:27:02

标签: ruby minitest

我偶然发现了一个奇怪的行为,却无法弄清楚我在做什么错。我希望有人能启发我。

在Rails应用程序中进行测试时,我试图对Redis客户端进行存根。因此,我正在使用MockRedis宝石。我已经用单个类方法RedisFactory创建了一个.create类,我想使用一个可选的MockRedis实例对它进行存根,如下所示:

def stub_redis(mock_redis = MockRedis.new)
    RedisFactory.stub :create, mock_redis { yield }
end

这没有用,总是抛出ArgumentError in Foo#Bar wrong number of arguments (0 for 1)。进一步的调试显示,在RedisFactory.create 'foo'块内调用stub导致错误'foo' is no method on instance of MockRedis::Database

但是,我已经可以使用下面的代码片段使用lambda函数来 catch 传入的参数来解决此问题:

def stub_redis(mock_redis = MockRedis.new)
    RedisFactory.stub(:create, ->(*_args) { mock_redis }) { yield }
end

有人可以解释这种行为吗?

1 个答案:

答案 0 :(得分:1)

到目前为止,MiniTest会通过检查是否对val_or_callable做出响应来尝试猜测传递的Proc是否为call,参见:

不幸的是,在这种特定情况下,Redis以及传递的MockRedis实例都提供了执行Redis命令的通用call方法,请参见:

您已经找到正确的解决方法。在这种情况下,您唯一的机会是显式使用stub的proc版本。

注意:在Ruby中,有些社区使用def call作为ServiceObjects的模式,而使用minitest的stub可能会很困难。在seattlerb/minitest中打开一个问题可能是个好主意。