Decoupling unit tests in larger apps can get pretty hairy, especially for newer developers whose classes probably call each other 19 times a millisecond. Not calling anyone out; we all know the struggle. In TDD mocks are a strategy to create doubles of actual objects in the program to help isolate what is being tested independently. They allow us to test certain classes or functions without needing to call other objects we are building in the program, lest our unit tests become unwilling integration tests. Some programmers view mocks as code smell pointing to the larger program of highly coupled objects in your code, but for the purpose of this post, let’s view mocks as a very useful TDD tool that can help isolate what you specifically want to test.
RSpec, like it does with everything, makes creating mocks very intuitive with the #double method. The first argument the method takes is a string, which is just a name or identifier for the double object. The second argument #double can take is a hash, the keys of which represent method calls, and the values that stand in for return values. We can then test our doubles as we would any other object with RSpec. E.G:
Though both those tests pass, it’s important to keep in mind ay sort of internal logic or process to the double doesn’t matter. You don’t have to code any actual methods or properties; RSpec just checks that the method call exists and simply returns what the value is. Doubles are strict by default, meaning any call undefined by you will fail the test.
There are two more common syntaxes using the methods #receive and #return that accomplish the same as above. The second syntax is a method stub, and those can actually also be used on real objects, not just doubles. The third option is using message expectations:
It’s that easy, folks. In a real example group, instead of having to worry about a not-yet-coded class or object, we can now just define a double and plug it into what we are specifically testing, leading to nicely decoupled unit tests that focus only on what matters to them.
RSpec also allows the use of verifying doubles as a stricter alternative to the normal doubles outlined above. They are especially useful when using instance and class doubles as verifying doubles check whether the message being stubbed is actually available in the real class. For more info check this out.