Additional Concepts
All right, you're almost at the end! Below are a few additional concepts of testing that may helpful in your future testing adventures.
Doubles and stubs
Doubles are simpler objects that represent objects from your application.
orange = double(:orange)
If you instantiate that double in your test file, you have access to orange in your tests to test with. This is instead of creating an entire Orange model in ActiveRecord. If you need to create many different test objects with different properties, FactoryGirl is a great gem for that purpose and will allow persistence or in-memory object creation, depending on your testing situation.
Stubs can be used to dictate what is returned when a method is called on a double.
orange.stub(:name).and_return("Florida Orange")
So, when you write a test that calls the title attribute of the orange double, you'll always get back the string Florida Orange. Got it? Good!
Spies
With spies, we are not talking about espionage... at least, not in relation to testing :) Spies can be used to verify whether a method was called on an object a certain number of times. For instance (assume you already have the orange double from above):
orange = spy('orange') orange.name expect(orange).to receive(:name) orange.name expect(orange).to receive(:name).exactly(2).times
Obviously, this is a simplified case. Instead of orange.name, you might have a complicated method that executes many functions internally and that's where spies can come in handy; they can check easily whether one specific method was called. Capiche? Ok, let's keep on trucking!
Webmock
What if your app relies on third-party services or applications, known amongst friends as application programming interfaces or APIs? Well, it seems like APIs should also be tested but should our test suite really be dependent on someone else? NOPE! What if the API goes down? Or is slow? Welcome to the stage: Webmock! Webmock is a gem that stubs out external HTTP requests. Once you include the gem, bundle install, and include the below code snippet in your spec helper file (which is included in every test file), you're good to go.
require 'webmock/rspec' WebMock.disable_net_connect!(allow_localhost: true)
Then, you can start stubbing out API requests in your spec helper file. Let's write an example for Bitly, a service that shortens long URLs. This may come in handy when you want to provide external links to info pages about the different types of oranges in your orange tree but the links are too long to display on a line.
RSpec.configure do |config| config.before(:each) do stub_request(:get, /api.bitly.com.v3.shorten/). with(headers: {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}). to_return(status: 200, body: "stubbed response", headers: {}) end end
So, if you write any tests in your test files that call the Bitly API, then the response will be whatever you defined above. The test will prevent the actual API request from being made. Pretty cool, huh?
Awesome, you are now equipped with a license to TEST! Go forth and create doubles, stubs, and spies in your app (at least one of each and have a TA verify). And, if you have time for a final challenge (optional), click below...
Next Step:
Go on to Final Challenge