简体   繁体   中英

Ruby spec expected: 1 time with any arguments received: 0 times with any arguments

Getting an error running my spec and I am guessing that it may be that update_all has been deprecated. I must be missing something obvious

Code:

def update_the_members_email
    self.the_members.update_all(email: self.email)
end

Spec:

describe 'update_the_members_email' do

    describe 'when after_save is triggered' do
       let(:updated_email) { Faker::Internet.safe_email }
        before do
          user.email = updated_email
          user.save
        end
      it 'triggers update_all' do
        expect(user).to receive_message_chain(:the_members, :update_all).with({ :email => updated_email })
      end
    end
  end
end

Error:

`1) User update_the_members_email when after_save is triggered triggers update_all Failure/Error: expect(user).to receive_message_chain(:the_members, :update_all).with({:email => new_email })

  [....].the_members(*(any args))
       expected: 1 time with any arguments
       received: 0 times with any arguments

`

I have tried using update_column instead of update_all. Tried a few other ways of specing this out. Spent a ton of time researching.

Assuming update_the_members_email is called by an after save callback...

The mock has to be set up before the call. before happens before the test. So user.email happens before you've set your expectation. The expectation never sees it.

describe 'after save callbacks' do
  it 'updates all members email when the email is updated' do
    updated_email = Faker::Internet.safe_email

    expect(user).to receive_message_chain(:the_members, :update_all)
      .with(email: updated_email )

    user.update!(email: updated_email)
  end
end

Note that mocking is not necessary here. Just make sure the user has some members and test directly.

describe 'after save callbacks' do
  let(:updated_email) { Faker::Internet.safe_email }

  context 'when the user email is updated' do
    before do
      user.update!(email: updated_email)
    end

    it 'updates all members email when the email is updated' do
      # I'm assuming the user has members.
      expect(user.the_members).to all have_attributes(email: updated_email)
    end
  end
end

  • There's no need to append self to method calls. the_members.update_all(email: email)
  • Use the Ruby 2.0 style of passing named arguments: with(email: updated_email)
  • Try rubocop and rubocop-rspec to inform you about good style.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM