jansha
jansha

Reputation: 171

how to check if a method is called or not in rspec

as i try to check internally my method was calling or not in rspec but it got the following errors


context "#Meeting_schedule" do
    let(:meeting_schedule) { FactoryGirl.create(:meeting_schedule,:time=>"morning",:schedule_name=>"planned_meet", :schedule_info=>[{ "from"=>"00:00", "to"=>"00:01"}]) }

    it "if the same schedule was created again dont save it again" do 
      schedule.save
      params = {:time=>"morning",:schedule_name=>"planned_meet", :schedule_info=>[{ "from"=>"00:00", "to"=>"00:01"}]}
      meeting_schedule.create_or_update_meeting_schedule(params)
      expect(meeting_schedule).to receive(:updating_the_user)
    end
  end


i got the following error

Failure/Error: expect(meeting_schedule.create_or_update_meeting_schedule(params)).to receive(:updating_the_user)
       (#<Meeting_schedule:0x0055dbaf0da710>).updating_the_user(*(any args))
           expected: 1 time with any arguments
           received: 0 times with any arguments
     # ./spec/models/meeting_schedule_spec.rb:122:in `block (4 levels) 

so what was wrong in my code?

my method

def create_or_update_meeting_schedule(params)
   self.attributes = params
   if self.changed and self.save
     updating_the_user
   end
   self
end

can anyone help me out

Upvotes: 3

Views: 5928

Answers (1)

max
max

Reputation: 101811

Mocks must always be setup before the method under test is called as there is no reliable way to test if a normal method was called in Ruby. There are two ways of doing this in RSpec.

The first is using expect(...).to receive(...) which must be done before the method is called - this detaches the method and replaces it with a mock that wraps the original method.

The test will fail if the method is not called in the example.

The second is by using spies. You can either replace an entire object with a spy:

RSpec.describe "have_received" do
  it "passes when the message has been received" do
    invitation = spy('invitation')
    invitation.deliver
    expect(invitation).to have_received(:deliver)
  end
end

This "spy object" will keep track of any method you call on it.

You can also spy on a single method:

class Invitation
  def self.deliver; end
end

RSpec.describe "have_received" do
  it "passes when the expectation is met" do
    allow(Invitation).to receive(:deliver)
    Invitation.deliver
    expect(Invitation).to have_received(:deliver)
  end
end

Spies are very useful in the case when you want to mock the method in the test setup - for example in the before block.

class Invitation
  def self.deliver; end
end

RSpec.describe "have_received" do
  before do
    allow(Invitation).to receive(:deliver)
  end

  it "passes when the expectation is met" do
    Invitation.deliver
    expect(Invitation).to have_received(:deliver)
  end
end

Upvotes: 4

Related Questions