Reputation: 296
I have a very simple controller that looks like this.
module Veterinarians
module Dictionaries
class SpecialitiesController < ApplicationController
respond_to :json
skip_before_action :check_current_vet, only: %i( index )
def index
@specialities = Veterinarians::Speciality.all
respond_with(@specialities)
end
end
end
end
I have an rspec controller test that looks like this.
require 'rails_helper'
Rails.describe Veterinarians::Dictionaries::SpecialitiesController, type: :controller do
# Not returning a response body in JSON when testing RSPEC (https://github.com/rails/jbuilder/issues/32)
render_views true
routes { Veterinarians::Engine.routes }
let(:user) { double :user, id: 123 }
before { sign_in(user) }
context '#index' do
let(:speciality) { double :speciality, id: :some_id, value: :some_val }
before { allow(Veterinarians::Speciality).to receive(:all).and_return [speciality] }
subject { get :index, format: :json }
it { is_expected.to have_http_status(:ok) }
it { expect(JSON.parse(subject.body)).to include('id' => 'some_id', 'value' => 'some_val') }
end
end
The second example fails with this error.
expected [{"__expired" => false, "name" => "speciality"}] to include {"id" => "some_id", "value" => "some_val"}
Any hints as to why this would fail and where the hash with "__expired" is coming from?
I have other tests that are using this same method of testing that are successful.
Upvotes: 0
Views: 449
Reputation: 6620
You should use factories for creating your test data. Two most popular ones are FactoryGirl or FactoryBot.
Example:
FactoryGirl.define do
factory :user do
sequence(:email) { |n| "name#{n}@example.com" }
password 'password'
end
end
The sequence(:email)
will create you a different email for each user. More details can be found here.
Upvotes: 0
Reputation: 84114
Rails winds up calling to_json
on the double. You haven't stubbed that method on the double, so the to_json
method rails adds to Object
is called.
This implementation just dumps the instance variables of the object, which in this case is the internal state of the test double.
You could stub to_json
on the double, although your spec wouldn't be testing a whole lot at that point.
Upvotes: 0
Reputation: 11076
I suspect this is coming from RSpec's internal representation of a double:
https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/test_double.rb#L10
RSpec's doubles sometimes don't work well alongside Rails. Try instantiating a real Speciality
instance, or using something like FactoryGirl to do so.
Upvotes: 1