Reputation: 2633
I stumbled across a curious behaviour and haven't been able to figure out what I was doing wrong. I hope somebody can enlighten me.
I was trying to stub the Redis client during my tests in a Rails application. Therefore I was using the MockRedis gem. I have created a RedisFactory
class with the single class method .create
, which I wanted to stub with an optional MockRedis
instance like so:
def stub_redis(mock_redis = MockRedis.new)
RedisFactory.stub :create, mock_redis { yield }
end
This did not work and always threw a ArgumentError in Foo#Bar wrong number of arguments (0 for 1)
. Some further debugging revealed that a call of RedisFactory.create 'foo'
within the stub
-block resulted in an error that 'foo' is no method on instance of MockRedis::Database
.
However, I have been able to solve this problem with the following code snippet, using a lambda function to catch the incoming arguments:
def stub_redis(mock_redis = MockRedis.new)
RedisFactory.stub(:create, ->(*_args) { mock_redis }) { yield }
end
Could anybody explain this behaviour?
Upvotes: 1
Views: 1282
Reputation: 992
As of now MiniTest tries to guess if the passed val_or_callable
is a Proc
by checking whether it responds to call
, cf.:
Unfortunately, in this specific case Redis
as well as the passed MockRedis
-instance both provide a generic call
-method for executing Redis commands, cf.:
You already found the correct workaround. In this case, your only chance is to explicitly use the proc-version of stub
.
Note: There are some communities using def call
as a pattern with ServiceObjects in Ruby which may have a difficult time using minitest's stub
. It is probably a good idea to open an issue in seattlerb/minitest.
Upvotes: 1