I'm writing unit tests using Minitest with Ruby on Rails.
Occasionally I need to mock multiple things at once.
For example, when testing an action that triggers notifications to users, I might want to mock two external servers (example: SmsClient and EmailClient) in one go.
I can do this as follows:
test 'my test case' do
SmsClient.stub :send, nil do
EmailClient.stub :send, nil do
get my_controller_url
end
end
end
This works, however I now need to mock one more class on the same call.
I'm concerned that my nesting of these stub calls is going to get out of control.
Question: Is there a way I can setup a mock on these services without using the nesting?
Note: These examples are just a hypothetical.
I don't know if there are any Minitest helpers to simplify this, but here is some core Ruby code that could reduce nesting.
To understand this answer you have to know that:
Can also be written as:
Each item in the
subsarray is aproc, that accepts a block, and returns a new proc that is passed to another element.stubs.reduce(:<<)will create a composed proc that passes any argument to the last element, the return value of that proc is passed the the element before it.Note that
bis still a proc so we need to call.callagain on the final return value.Here is an image to help you understand what is happening in the code above:
Note that you could invert the nesting by changing
:<<into:>>.You could define a helper to abstract away the common logic: