Let's take the Notifications
example:
class Notifications
def as_json
# Fetch latest notifications via HTTP API
end
end
class NotificationsController
def index
render json: { data: notifications.as_json }
end
def notifications
Notifications.new
end
end
To avoid requesting remote API in tests, we use a double
:
describe "NotificationsController#index" do
let(:notifications) do
double(:datasource, as_json: { notifications: [] })
end
before do
allow(Notifications)
.to receive(:new)
.and_return(notifications)
end
it "wraps notifications in 'data' key" do
get :index, format: :json
expect(json_response["data"])
.to have_key "notifications"
end
end
What happens if we rename Notifications#as_json
to Notifications#to_json
? Nothing. We will be left alone with a green test checking a useless double.
instance_double
To avoid getting into a situation described above, use instance_double
:
describe 'NotificationsController#index' do
let(:notifications) do
instance_double(Datasource, as_json: { notifications: [] })
end
# ...
end
Such a double will test its interface. If there is no method as_json
or it has other arguments, it will fail the test.
To check mocks and stubs in the same way, make sure that verify_partial_doubles is enabled in spec_helper.rb.
Top comments (0)