additional_concepts.step

message <<-MARKDOWN
  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.

  ```ruby
  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.

  ```ruby
  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.
  For instance (assume you already have the orange double from above):

  ```ruby
  orange = spy('orange')
  orange.name
  expect(orange).to have_received(:name)
  ```

  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.
MARKDOWN

source_code :ruby, <<-RUBY
  require 'webmock/rspec'
  WebMock.disable_net_connect!(allow_localhost: true)
RUBY

message <<-MARKDOWN
  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.
MARKDOWN

source_code :ruby, <<-RUBY
  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
RUBY

message <<-MARKDOWN
  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...
MARKDOWN

next_step "final_challenge"