Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice or workaround for RSpec specs faking class constants

Let's say I have classes Car and Mechanic. Car has "run" method. Mechanic requires Car for some reason. Then I write RSpec specs. In mechanic I define a fake clas like this:

class Car; end

and later stub the method that mechanic uses on it. All works fine if I run tests seperately. But when I run both tests together (rspec spec/directory/) my Mechanic specs use real Car class.

So. I guess this is because ruby classes are "open" and I already loaded the class once for Car specs. But is there a better way to do this? What are best practices for this kind of situations? Does this mean my code needs some improvements cause it's probably tightly coupled?

I made a quick demo in github: https://github.com/depy/RspecTest

like image 546
Matjaz Muhic Avatar asked Nov 28 '12 17:11

Matjaz Muhic


2 Answers

This fake class wont work since Ruby Classes are open.

One approach you could be using is to use let to initialize the objects the way you want, and if needed work with the relationship on a before block. Stubs are welcome as well inside the before blocks. =p

Hope this helps you!

like image 179
Paulo Henrique Avatar answered Nov 06 '22 17:11

Paulo Henrique


I think what you need is two-layer testing:

  • unit specs: testing each class in isolation
  • integration specs: testing as a whole

Given the code as follows:

class Car
end

class Mechanic
  def fix(car)
    # do something here
  end
end

For unit specs I would stub the dependencies, for example:

describe Mechanic do
  let(:mechanic) { described_class.new }
  let(:car)      { stub(stubbed_method_on_car: 14) } # Or just OpenStruct.new(stubbed_method_on_car: 14)

  it 'does some stuff' do
    mechanic.fix(car).should eq true
  end
end

For integration specs I would do this:

describe Mechanic do
  let(:mechanic) { FactoryGirl.create(:mechanic) }
  let(:car)      { FactoryGirl.create(:car) }

  it 'does some stuff' do
    mechanic.fix(car).should eq true
  end
end
like image 2
Tomek Wałkuski Avatar answered Nov 06 '22 17:11

Tomek Wałkuski