如何从控制器中的模块中存根方法?

时间:2015-10-05 09:00:22

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

lib/modules/api.rb

module Api
  require 'net/http'
  require 'json'

  def send_get_request(url, body)
    # some logic
  end
end

控制器:

class DashboardController < ApplicationController
  include Api

  def index
    response = send_get_request(_some_, _params_)[:json]
    @something = response['something']
  end
end

如何存根send_get_request方法?我尝试了一项功能测试:

require 'rails_helper'

describe 'visiting users page' 
  it 'shows users page' do
    visit '/'
    allow_any_instance_of(Api).to receive(:send_get_request).with(any_args).and_return({json: {'total_paying' => '3'}})
    within('#side-menu') do
      click_link 'Users'
    end
    expect(page).to have_selector('.page-header', text: 'Users')
  end
end

但显然它不起作用(测试失败,因为真正的send_get_request方法被调用不正确的参数(它们在测试中)。

当我尝试

expect_any_instance_of(Api).to receive(:send_get_request).once

期望已经过去了。

1 个答案:

答案 0 :(得分:1)

嗯,这是接收消息的控制器。作为客户,测试不关心如何定义方法,“正常”或混合。

如果是控制器规格,你可以这样做:

 allow(controller).to receive(:send_get_request).with(...)

至于功能规格,请不要在那里存根。它应该是“真正的”互动。在功能规范中,您使用capybara(或其他东西)来填充表单,然后检查数据库(以查看用户是否已创建等)。

要屏蔽外部API的功能规格,您可以使用VCR gem。它基本上运行你的外部查询一次,将响应写入文件,然后,在后续运行中,只播放它,而不再联系外部api。