Jezen Thomas
Jezen Thomas

Reputation: 13800

How do I stub a class method with a class_double in RSpec?

I’m trying to write a simple isolated test for a controller method in my Rails 4 app. The method takes an ID from a query string, asks the Project model to give me some rows from the persistence layer, and render the result as JSON.

class ProjectsController < ApplicationController

  def projects_for_company
    render json: Project.for_company(params[:company_id])
  end

end

I’m struggling with stubbing the for_company method. Here is the code I’m trying:

require "rails_helper"

describe ProjectsController do

  describe "GET #projects_for_company" do

    it "returns a JSON string of projects for a company" do
      dbl = class_double("Project")
      project = FactoryGirl.build_stubbed(:project)
      allow(dbl).to receive(:for_company).and_return([project])
      get :projects_for_company
      expect(response.body).to eq([project].to_json)
    end

  end

end

Since I’ve stubbed the for_company method, I expect the implementation of the method to be ignored. However, if my model looks like this:

class Project < ActiveRecord::Base

  def self.for_company(id)
    p "I should not be called"
  end

end

…Then I can see that I should not be called is actually printed to the screen. What am I doing wrong?

Upvotes: 14

Views: 10360

Answers (1)

Frederick Cheung
Frederick Cheung

Reputation: 84114

class_double doesn't actually replace the constant. You can call as_stubbed_const to replace the original

class_double("Project").as_stubbed_const

This is the just a convenience wrapper around stub_const

Upvotes: 24

Related Questions