When writing tests in Capybara, you often want to isolate specific portions of a class. You might want to create a unit test, or perhaps you just don’t have the required connection access to pull data required by a class method.
Within a Capybara test, it is possible to mock the response of a controller method before it is instantiated. So, for example, you can have this Ruby class:
Notice how picture_url depends on an external class AssetsUrl to get the main part of an image URL (perhaps all of your employee profile pictures reside in the same external server); but that class might not be available in your unit test scope (or available within your UI test permissions), so you might want to mock that response in order to proceed with your tests.
You can mock any calls to picture_url completely by using allow_any_instance_of to force any call to it responding what you need, by adding this to your Capybara test:
The before definition instructs the Capybara test set to run this part before any proper test (as defined by any it block), and can be included within either a context or a describe block. The allow_any_instance_of statement allows you to mock a class before it’s instantiated, and you can specify the method you want to mock using receive (in this case, picture_url) and the response you want the method to return.
You could also mock AssetsUrl, so that Employee still calls for it, but its response will be the one you actually want to mock, like so:
Furthermore, you could also mock the response for a method based on the parameters it’s being called with. Suppose you had a more generic get_url (instead of get_main_url) defined in AssetsUrl, which receives work_area, an area identifier that determines the asset’s base URL. Something like this:
You might then want to test Employee for a particular work area. For example, you might want to test the Employee class for a worker in development, but then use the same test set to actually fetch the real data for the sales work area. To do so, you want to change them before the statement to something like this:
By using the with method, you can instruct allow_any_instance_of to be called only when invoked with that particular parameter, just as you did with the receive method before. Whenever AssetsUrl gets invoked with any method other than get_url, or whenever get_url is called with a parameter other than developing, then the main definition will be executed (with no mocking behavior).
Finally, if you want to reset the original behavior for a particular test, you can always overwrite the mocking behavior with the original behavior using this line:
This line will just call the original method, ignoring any mocks defined in a before block.
We’d love to learn more about your project. Contact us below for a free consultation with our CEO.
Engagements start at $50,000.