Ben Downey
Ben Downey

Reputation: 2665

How to stub out a entire class

I'm starting the process of refactoring my tests to run without loading Rails. Most of my tests are still standard rspec tests that load rails. My problem is that in the test file below, I override one class that is used in many other test files. So even when these tests pass, the others fails. I'm looking to stub that Project class after getting a lot of advice here. (I would rather stub the project class in this file than to reload the project class in all the other test files that need it.)

Here's what I have now.

require 'active_model'
require 'active_model/validations'
require 'active_record/callbacks'
require 'active_support/core_ext/string' #used for '.blank?' method


class Project
  attr_accessor :general_media
  def initialize(attributes = {})
    @general_media = attributes[:general_media]
  end
  include ActiveModel::Validations    
  include ActiveRecord::Callbacks
end

require_relative '../../../app/models/project/media.rb'

describe 'Project::Media' do
  #then all the tests

I tried to to create a FakeProject class and to have Project::Media inherit from that by stubbing Project with FakeProject, but it didn't work. Here's what I've got.

require 'active_model'
require 'active_model/validations'
require 'active_record/callbacks'
require 'active_support/core_ext/string' #used for '.blank?' method


class FakeProject
  attr_accessor :general_media
  def initialize(attributes = {})
    @general_media = attributes[:general_media]
  end
  include ActiveModel::Validations    
  include ActiveRecord::Callbacks
end
class Project; end
require_relative '../../../app/models/project/media.rb'

describe 'Project::Media' do
  before(:all) { stub_constant!("Project", FakeProject) }

First off, I'm still overriding the project class and secondly, the stubbig isn't working. I still get an error about validations not working.

undefined method `validate' for Project::Media:Class (NoMethodError)

Any suggestions? My goal is to stub the Project class only for the tests in this media_spec.rb test file rather than override how the Project class behaves for all tests.

Upvotes: 1

Views: 2211

Answers (1)

Ramandeep Singh
Ramandeep Singh

Reputation: 5253

You can create a Fake class using the rspec syntax. Something like:

let(:fake_class) { Class.new }
stub_const("Project", fake_class)

And if you want to stub any method for that Project class, you can do like :

dummy_class = Project # the same name that you used above
# stub any method and return anything that you want to return
dummy_class.stub_chain(:any_method).and_return(anything) 

Upvotes: 14

Related Questions