【问题标题】:How do I check if an API was called during a test如何检查测试期间是否调用了 API
【发布时间】:2023-03-22 20:57:01
【问题描述】:

我希望我们的应用与我们的微服务对话,以便通过 API 发送电子邮件。

在测试中(在 RSpec 中),我想说:

  1. 做点什么
  2. 我希望微服务已被调用/未被调用。

例如:

  1. 创建用户
  2. 我希望已发送欢迎电子邮件。

【问题讨论】:

  • 假设您正在尝试捕获和测试对应用程序外部 API 的 HTTP 调用,请查看 VCR - github.com/vcr/vcr

标签: ruby-on-rails ruby


【解决方案1】:

你需要使用message expectations,例如:

it "asks the project to trigger all hooks" do
  expect(project).to receive(:execute_hooks).twice
  expect(project).to receive(:execute_services).twice
  expect(project).to receive(:update_merge_requests)

  PostReceive.new.perform(...)
end

关于邮寄者请查看其他answer

【讨论】:

  • 已编辑 - 消息期望和期望消息不是一回事。
【解决方案2】:

从您的应用发送真正的 HTTP 请求可能有一些严重的缺陷:

  • 由于连接问题导致测试失败。
  • 测试套件速度极慢。
  • 在第 3 方网站上达到 API 速率限制
  • 服务可能尚不存在(仅提供相关文档)。
  • 非确定性响应可能导致抖动测试。
  • API 可能不提供沙盒或测试模式。

您还需要权衡每个应用程序与测试敏锐度的明确界限。正确尊重应用程序边界意味着您只测试您的应用程序是否与 API 指定的协作者进行通信,并排除实际通信。

当然,在测试敏锐度时,存根总是要付出代价的。您可能会错过 API 无法按文档说明工作的错误,或者您只是在测试错误的东西。

例如,

Webmock 可以让您完全去除 HTTP 层。您可以对外部调用设置期望值并模拟返回值。

stub_request(:post, "api.example.com").to_return(status: 201)

expect(a_request(:post, "www.example.com").
  with(:body => {"a" => ["b", "c"]},
    :headers => {'Content-Type' => 'application/json'})).to have_been_made
另一方面,

VCR 是一种中间道路,它允许您执行真实的 HTTP 请求,将其记录到 YML 文件中,然后回放结果。随后的运行速度更快且具有确定性。 VCR 比设置模拟响应要简单得多,但是您仍然需要处理设置初始状态并从测试中清除对外部服务的任何副作用。

VCR.use_cassette("synopsis") do
  response = Net::HTTP.get_response(URI('http://example.com'))
  expect(response.body).to match("Example domain")
end

这是一个从使用 Flickr API 的真实应用中提取的示例:

RSpec.feature 'Importing photosets from flickr' do

  include JavascriptTestHelpers

  let(:user) { create(:admin, flickr_uid: 'xxx') }

  before { login_as user }

  let(:visit_new_photosets_path) do
    VCR.use_cassette('photosets_import') { visit new_photoset_path }
  end

  scenario 'When I create a photoset it should have the correct attributes', js: true do
    visit_new_photosets_path
    VCR.use_cassette('create_a_photoset') do
      click_button('Create Photoset', match: :first)
      wait_for_ajax
    end
    find('.photoset', match: :first).click
    expect(page).to have_content "Showcase"
    expect(page).to have_content "Like a greatest hits collection, but with snow."
    expect(page).to have_selector '.photo img', count: 10
  end
end

【讨论】:

    猜你喜欢
    • 2021-07-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 2020-02-19
    • 1970-01-01
    • 2013-08-22
    • 1970-01-01
    • 2021-08-03
    相关资源
    最近更新 更多