Writing tests is important (yes, we all know that) and it’s taken me a couple of years to get familiar with writing tests with RSpec. Learning to write method stubs, fakes, working with test doubles and working around caveats - big and small. For example: not every class is required to test what the usecases or classes within it return. It might be sufficient in these scenarios to get away with rspec-mocks, RSpec’s test double-framework. While first learning about RSpec I often got stuck with the test setup using mocks. There’s a plethora of blogs and Stack Overflow posts about this, these are just some that I didn’t come across as easily and the ones I use repeatedly in testing.
- Using stub/unstub
This is the ‘old’ way of allowing messages but has come in handy in a recent implementation. For example in the loop scenario where the first call on an object needs stubbing, but the second does not to replicate intended behaviour of the loop.
- Configuring responses with
and_return
and instance_doubles
This is handy when you want to set up your test with some responses. You may have a class that calls another usecase. In this case you can mock the messages to the class and return a mock of intended usecase and even mock the usecase itself. For example:
- Another commonly used example is the block implementation where you require a bit more flexibility but also allows you exactly match the method calls. You can mock the arguments and the return values of the block. For example:
- Chaining method calls
Passing messages by allowing messages to be received. Similar to the above but here we link the mocks. For example:
- Open Structs vs Instance Doubles
Both do same thing in terms of faking objects, however I personally find instance_doubles easier to follow. An example of an OpenStruct for the usecase double above could be:
I’ve been working through the book Ruby on Rails Tutorial (6th Edition) by Michael Hartl. With books such as these, I like to code along and work through the exercises no matter how tedious they may be. Without going into too much detail to avoid copyright infringement I came across a local routing error which seemed quite odd.
In Chapter 9 I came across an instance where a DELETE request to simply follow a rails destroy action threw a rails routing error when I tried to test the logout feature of the app in the browser. The app uses jQuery to render the front-end. The rails code was a standard DELETE request:
The error I received was a Routing Error: No route matches GET /logout. Except this wasn’t a GET request but a DELETE request which should be destroying a record in rails terms.
After much digging I discovered the link_to tag is tied to a GET request. So as a temporary patch I changed this to button_to with the method param set to delete which creates a POST request to delete the record.
This works, however the tests will fail if you have been coding along as the rest of the book relies on this code. But for testing in the browser this patch works.
In the real world you will need a proper way to deal with this and I certainly would fix it and use something like the Devise gem for authentication.
There’s plenty of answers on stackoverflow but the one I found most useful was https://stackoverflow.com/questions/44050190/no-route-matches-get-logout.