Oved D
Oved D

Reputation: 7442

Issue using RSpec to pass parameters to mocked model method in Rails controller action

I'm trying to mock a user models save method to return false, and simulate what the controller would do in case of validation failure.

My spec looks like:

require 'spec_helper'

describe UsersController do
  describe 'POST create_email_user' do
    it 'responds with errors json if saving the model fails' do
      @params = {
        :last_name => 'jones',
        :email => 'asdfasdfasfd@'
      }
      User.stub(:new_email_user) .with(@params) .and_return(@mock_user)

      @mock_user.stub(:save) .and_return(false)

      post :create_email_user, :user => @params, :format => :json

      response.body.should == @mock_user.errors.as_json
      response.status.should == :unprocessable_entity
    end
  end
end

Controller action looks like:

class UsersController < ApplicationController
  def create_email_user
    @user = User.new_email_user(params[:user])
    if @user.save
      # code left out for demo purposes
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end
end

When running this spec, I get the error that basically says the expected call to new_email_user got the wrong arguments:

  1) UsersController POST create_email_user responds with errors json if saving the model fails
     Failure/Error: post :create_email_user, :user => @params, :format => :json
       <User(id: integer, email: string, encrypted_password: string, reset_password_token: string, reset_password_sent_at: datetime, remember_created_at: datetime, sign_in_count: integer, current_sign_in_at: datetime, last_sign_in_at: datetime, current_sign_in_ip: string, last_sign_in_ip: string, created_at: datetime, updated_at: datetime, uid: string, provider: string, first_name: string, last_name: string, registration_id: integer, gender: string, authentication_token: string) (class)> received :new_email_user with unexpected arguments
         expected: ({:last_name=>"jones", :email=>"asdfasdfasfd@"})
              got: (["last_name", "jones"], ["email", "asdfasdfasfd@"])
        Please stub a default value first if message might be received with other args as well. 

It seems like rails converts the has to an array of key value pairs, while my code is just using the straight hash in the setup.

How can I simulate this converting to an array, or am I doing else wrong?

Upvotes: 2

Views: 6846

Answers (1)

Daniel Evans
Daniel Evans

Reputation: 6808

Drop the .with stub on user, since it isn't really relevant to the test and it is causing problems.

Without the .with the stub will return that value for any arguments. So:

User.stub(:new_email_user).and_return(@mock_user)

I would then have a separate spec which ensures that:

User.should_receive(:new_email_user).with(@params)

And diagnose that problem in its own, narrow spec.

Upvotes: 5

Related Questions