Unit Tests

Now that we have some integration tests in place testing our end to end actions, let's test out all the edge cases for the classes in our ReadingRequests namespace!

Rules

  • Only use doubles
  • If you find yourself testing a query or wanting to test a private method, refactor and stub it out

Example

Below is the code to unit test our ReadingRequests::Initiate class.

require 'rails_helper'
require 'reading_requests/initiate'

RSpec.describe ReadingRequests::Initiate do
  let(:cat) do
    instance_double(Cat,
      book_requests: double(create!: true)
    )
  end

  let(:request_data) { { some: 'data' } }

  let(:wrangler) do
    instance_double(CatReadingWrangler,
      user: instance_double(User)
    )
  end

  before do
    allow(ReadingRequests::Eligibility)
      .to receive(:call)
      .with(cat: cat)
      .and_return(eligiboolean)
    allow(CatReadingWrangler)
      .to receive(:where)
      .with(available: true)
      .and_return([wrangler])
  end

  subject do
    described_class.call(cat: cat, request_data: request_data)
  end

  context 'When the cat is eligible' do
    let(:eligiboolean) { true }

    it "creates a book request and alerts the wranglers" do
      expect(cat.book_requests)
        .to receive(:create!)
        .with(
          status: BookRequest::STATUSES[:initiated],
          request_data: request_data
        )

      expect(ReadingRequestMailer)
        .to receive(:new_request)
        .with(wrangler.user)
        .and_return(double(deliver_now: nil))

      subject
    end
  end

  context 'When the cat is NOT eligible' do
    let(:eligiboolean) { false }

    it "does NOT create a book request; notifies NOBODY" do
      expect(cat.book_requests).not_to receive(:create!)
      expect(ReadingRequestMailer).not_to receive(:new_request)

      subject
    end
  end
end

Now go forth and write full unit tests for all the classes in lib/reading_requests.

Note -- You'll notice a lot of the classes in the ReadingRequest namespace use a gem called Verbalize. Read up on Verbalize here and compare ReadingRequests::Initiate and ReadingRequests::Checkout to see how Verbalize allows you to easily write single purpose action-oriented classes.

Further challenges...

  • Refactor queries into scopes and test them in the model specs
  • Write a test expecting to raise an error
  • Write a test expecting to receive something n number of times
  • Search the code base for TODOs -- I left a few in there

And beyond...

  • Feature tests in Rails!
  • Acceptance testing
  • Hooking this repo up to a CI

results matching ""

    No results matching ""