Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSpec before in a helper

Is it possible to do something like this?

module MyHelper
  before (:each) do
    allow(Class).to receive(:method).and_return(true)
  end
end

Then in my tests I could do something like:

RSpec.describe 'My cool test' do
  include MyHelper
  it 'Tests a Class Method' do
    expect { Class.method }.to eq true
  end
end

EDIT: This produces the following error:

undefined method `before' for MyHelper:Module (NoMethodError)

Essentially I have a case where many tests do different things, but a common model across off of them reacts on an after_commit which ends up always calling a method which talks to an API. I dont want to GLOBALLY allow Class to receive :method as, sometimes, I need to define it myself for special cases... but I'd like to not have to repeat my allow/receive/and_return and instead wrap it in a common helper...

like image 236
Nick Avatar asked Jan 24 '17 12:01

Nick


People also ask

What is before in RSpec?

You can also use before(:suite) to run a block of code before any example groups are run. This should be declared in RSpec. configure. Instance variables declared in before(:example) or before(:context) are accessible within each example.

What is subject in RSpec?

Summary: RSpec's subject is a special variable that refers to the object being tested. Expectations can be set on it implicitly, which supports one-line examples. It is clear to the reader in some idiomatic cases, but is otherwise hard to understand and should be avoided.

What is context in RSpec?

According to the rspec source code, “context” is just a alias method of “describe”, meaning that there is no functional difference between these two methods. However, there is a contextual difference that'll help to make your tests more understandable by using both of them.

What is allow in RSpec?

Use the allow method with the receive matcher on a test double or a real. object to tell the object to return a value (or values) in response to a given. message. Nothing happens if the message is never received.


Video Answer


2 Answers

You can create a hook that is triggered via metadata, for example :type => :api:

RSpec.configure do |c|
  c.before(:each, :type => :api) do
    allow(Class).to receive(:method).and_return(true)
  end
end

And in your spec:

RSpec.describe 'My cool test', :type => :api do
  it 'Tests a Class Method' do
    expect { Class.method }.to eq true
  end
end

You can also pass :type => :api to individual it blocks.

like image 53
Stefan Avatar answered Oct 11 '22 04:10

Stefan


It is possible to do things like you want with feature called shared_context

You could create the shared file with code like this

shared_file.rb

shared_context "stubbing :method on Class" do
  before { allow(Class).to receive(:method).and_return(true) }
end

Then you could include that context in the files you needed in the blocks you wanted like so

your_spec_file.rb

require 'rails_helper'
require 'shared_file'

RSpec.describe 'My cool test' do
  include_context "stubbing :method on Class"
  it 'Tests a Class Method' do
    expect { Class.method }.to eq true
  end
end

And it will be more naturally for RSpec than your included/extended module helpers. It would be "RSpec way" let's say.

like image 33
VAD Avatar answered Oct 11 '22 02:10

VAD