Getting around model filters
anicholson opened this issue · comments
I have a bunch of mutations that use model filters, like this one:
class UpdateEmailAddress < Mutations::Command
required do
model :user, new_records: true
string :email
end
def execute
user.email = email
user.save
end
end
I want to be able to test them using double()
s such as what RSpec provides. Unfortunately, they fail the :is_a?
test, and so the mutation never runs.
My current (kludgy) workaround is to do this:
class MockUser
def is_a?(klazz)
(klazz == User) ? true : super
end
attr_accessor :email
def save
true
end
end
describe UpdateEmailAddress do
it { should be_a Mutations::Command }
let(:user) { MockUser.new }
let(:new_address) { 'fred@example.org' }
let(:valid_input) {{ user: user, email: new_address }}
context 'all input correct' do
subject { described_class.run(valid_input) }
it { should be_success }
it 'sets the user\'s email and saves' do
user.should_receive(:save)
subject
user.email.should eq(new_address)
end
#snip...
end
end
Is there a better way I've missed?
There totally is: RSpec's mock_model
does exactly what I want. I can't believe I missed it!
describe UpdateEmailAddress do
it { should be_a Mutations::Command }
let(:user) { mock_model('User', email: 'old_address@example.org', save: true ) }
let(:new_address) { 'fred@example.org' }
let(:valid_input) {{ user: user, email: new_address }}
context 'all input correct' do
subject { described_class.run(valid_input) }
it { should be_success }
it 'sets the user\'s email and saves' do
user.should_receive(:save)
subject
user.email.should eq(new_address)
end
#snip...
end
end
PostScript:
Of course, if my models were POROs (or even AR models) then it wouldn't matter nearly as much. My problem was mimicing API persistance, so I had to test that things were at least trying to be saved.