cypriss / mutations

Compose your business logic into commands that sanitize and validate input.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.