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


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!


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
    

    Rspec已经构建支持存根常量。

    链接地址: http://www.djcxy.com/p/66694.html

    上一篇: 如何在所有分支上运行git svn rebase

    下一篇: RSpec规范伪造类常量的最佳做法或解决方法