djfm
djfm

Reputation: 2458

How to pass an external object to rspec tests?

I have a series of RSpec tests - each one living in their own files - that all need a specific object to be ran (shop).

Since setting up the shop object is complicated, I want to have a master file that builds the shop object and then passes it to all the RSpec test files in turn. The idea is that those writing the test scripts do not need to know anything about the setup step.

I could not figure out how to bring something from the outside world into an rspec test case. I have tried variations around the lines of this:

file master.rb:

describe "Testing tests/some_test.rb" do
  before :all do
    @shop = some_complex_operations
  end
  load 'tests/some_test.rb'
end

file tests/some_test.rb:

describe 'Some feature' do
  it 'should know about @shop'
    expect(@shop).not_to be nil
  end
end

When I run rspec master.rb then some_test.rb fails.

I know what I outlined is probably a very wrong way to go about this, but I hope at least you get the idea.

How can I implement such a thing cleanly?

Upvotes: 1

Views: 498

Answers (2)

Uri Agassi
Uri Agassi

Reputation: 37409

When you are writing a test, it should test one thing. shop might be a very complex object, which many objects and methods interact with, but I should guess none of them are aware of the complexity of shop - each method is interested in some aspect of shop.

Therefore I suggest that instead of building a complex object for each test, make a double of it, make it expect what's relevant, and then simply stub the rest:

describe 'Some feature' do
  let(:shop) { double('shop').as_nil_object }
  let(:my_object) { MyClass.new(shop: shop) }


  it 'should do something awesome with shop' do
    expect(shop).to receive(:awesome_data).and_return(my_data: 'is_this')

    expect(my_object.do_something_awesome).to eq 'how awesome is_this?'
  end
end

Upvotes: 0

Kostas Rousis
Kostas Rousis

Reputation: 6068

What you need is a global hook.

You can create a spec_helper and add there a before all global hook. For example:

RSpec.configure do |config|
  config.before(:each) do
    @shop = "in case you need a fresh instance of shop each time"
  end
  config.before(:all) do
    @shop = "in case you need a single instance (i.e. you don't modify it)"
  end
end

Then you should require this helper from each of your specs. The spec_helper can store any global hooks as well as helpers, or other dependencies for your tests.

Upvotes: 1

Related Questions