Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rspec allow and expect the same method with different arguments

Tags:

I want to test my method which runs method Temp::Service.run two times inside it:

module Temp
  class Service

    def self.do_job
      # first call step 1
      run("step1", {"arg1"=> "v1", "arg2"=>"v2"})


      # second call step 2
      run("step2", {"arg3"=> "v3"})


    end

    def self.run(name, p)
      # do smth

      return true
    end


  end
end

I want to test arguments provided to second call of method :run with first argument 'step2' while I want to ignore the first call of the same method :run but with first argument 'step1'.

I have the RSpec test

RSpec.describe "My spec", :type => :request do

  describe 'method' do
    it 'should call' do

      # skip this
      allow(Temp::Service).to receive(:run).with('step1', anything).and_return(true)

      # check this
      expect(Temp::Service).to receive(:run) do |name, p|
        expect(name).to eq 'step2'

        # check p
        expect(p['arg3']).not_to be_nil

      end


      # do the job
      Temp::Service.do_job

    end
  end
end

but I got error

expected: "step2"
     got: "step1"

(compared using ==)

How to correctly use allow and expect for the same method ?

like image 697
Max Ivak Avatar asked May 16 '17 13:05

Max Ivak


People also ask

How do I mock a method in RSpec?

Mocking with RSpec is done with the rspec-mocks gem. If you have rspec as a dependency in your Gemfile , you already have rspec-mocks available.

What is stub in RSpec?

In RSpec, a stub is often called a Method Stub, it's a special type of method that “stands in” for an existing method, or for a method that doesn't even exist yet.

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.

What is let in Ruby?

Use let to define a memoized helper method. The value will be cached. across multiple calls in the same example but not across examples. Note that let is lazy-evaluated: it is not evaluated until the first time. the method it defines is invoked.


1 Answers

Seems like you are missing the .with('step2', anything)

it 'should call' do

  allow(Temp::Service).to receive(:run).with('step1', anything).and_return(true)

  # Append `.with('step2', anything)` here
  expect(Temp::Service).to receive(:run).with('step2', anything) do |name, p|
    expect(name).to eq 'step2' # you might not need this anymore as it is always gonna be 'step2'
    expect(p['arg3']).not_to be_nil
  end

  Temp::Service.do_job
end
like image 86
Jay-Ar Polidario Avatar answered Sep 22 '22 10:09

Jay-Ar Polidario