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