expect和expect_any_instance_of之间的差异

时间:2016-07-18 06:32:33

标签: ruby-on-rails ruby rspec rspec-mocks

我的控制器中的方法如下所示:

def resend_confirmation
  @current_user.send_confirmation_instructions

  render json: nil, status: 200
end

我已按照该方法的规范编写:

require 'rails_helper'

describe 'POST /api/v1/users/:id/resend_confirmation' do
  let!(:current_user) { create(:user) }

  before do
    expect(current_user).to receive(:send_confirmation_instructions)

    post resend_confirmation_api_v1_user_path(current_user),
         headers: http_authorization_header(current_user)
  end

  describe 'response' do
    it 'is empty' do
      expect(response.body).to eq 'null'
    end
  end

  it 'returns 200 http status code' do
    expect(response.status).to eq 200
  end
end

但问题是这个规格没有通过。这条线路失败了:

expect(current_user).to receive(:send_confirmation_instructions)

当我将其更改为

expect_any_instance_of(User).to receive(:send_confirmation_instructions)

一切都很顺利。有人可以解释一下为什么带有expect语法的规范没有通过吗?

编辑:

错误的显示方式:

Failures:

  1) POST /api/v1/users/:id/resend_confirmation returns 200 http status code
     Failure/Error: expect(current_user).to receive(:send_confirmation_instructions)

       (#<User id: 4175, email: "test1@user.com", date_of_birth: "1990-01-01", created_at: "2016-07-18 06:56:52", updated_at: "2016-07-18 06:56:52", sex: "male", touch_id_enabled: false, first_name: "Test", last_name: "User", athena_health_patient_id: nil, photo_url: nil, admin: false, one_signal_player_id: "1", phone_number: nil, state: nil, address: nil, city: nil, zip_code: nil, phone_number_confirmed: false>).send_confirmation_instructions(*(any args))
           expected: 1 time with any arguments
           received: 0 times with any arguments
     # ./spec/requests/api/v1/user/resend_confirmation_spec.rb:7:in `block (2 levels) in <top (required)>'

  2) POST /api/v1/users/:id/resend_confirmation response is empty
     Failure/Error: expect(current_user).to receive(:send_confirmation_instructions)

       (#<User id: 4176, email: "test2@user.com", date_of_birth: "1990-01-01", created_at: "2016-07-18 06:56:53", updated_at: "2016-07-18 06:56:53", sex: "male", touch_id_enabled: false, first_name: "Test", last_name: "User", athena_health_patient_id: nil, photo_url: nil, admin: false, one_signal_player_id: "2", phone_number: nil, state: nil, address: nil, city: nil, zip_code: nil, phone_number_confirmed: false>).send_confirmation_instructions(*(any args))
           expected: 1 time with any arguments
           received: 0 times with any arguments
     # ./spec/requests/api/v1/user/resend_confirmation_spec.rb:7:in `block (2 levels) in <top (required)>'

1 个答案:

答案 0 :(得分:1)

expects(...)设置特定实例的期望值。执行POST请求时,您的应用将尝试识别请求信息中引用的用户,并将创建一个代表它的实例。

但是,该实例与您在测试中准备的实例不同。它确实引用了相同的用户对象,但它不是同一个Ruby对象。

因此,在测试中,使用的current_user不是您设定期望的那个。

使用expect_any_instance_of会影响创建的每个用户实例,因此也会影响为满足请求而创建的用户。