使用 Minitest 惯用地模拟 OpenURI.open_uri

2023-11-29

我有调用的代码OpenURI.open_uri我想确认调用中使用的 URI(因此存根对我不起作用),但也拦截调用。我希望不必抽象出对OpenURI.open_uri仅用于测试目的。我想出的东西似乎冗长且过于复杂。

测试下.rb

require 'open-uri'

class UnderTest
  def get_request(uri)
    open(uri).read
  end
end

测试下的测试.rb

require 'minitest/autorun'
require './lib/under_test'

class TestUnderTest < Mintest::Test
  def test_get_request
    @under_test = UnderTest.new
    mock_json  = '{"json":[{"element":"value"}]}'
    uri = URI('https://www.example.com/api/v1.0?attr=value&format=json')
    tempfile = Tempfile.new('tempfile')
    tempfile.write(mock_json)

    mock_open_uri = Minitest::Mock.new
    mock_open_uri.expect(:call, tempfile, [uri])

    OpenURI.stub :open_uri, mock_open_uri do
      @under_test.get_request('https://www.example.com/api/v1.0?attr=value&format=json'
    end

    mock_open_uri.verify
  end
end

我是否误用或误解了 Minitest 的嘲笑?

跳舞的一部分是我也在创造一个Tempfile这样我的read调用成功。我可以把它存起来,但我希望有一种方法可以阻止调用链接近开头。


对于这个问题,测试间谍可能是可行的方法:

A test spy是一个记录其所有调用的参数、返回值、this 值以及抛出的异常(如果有)的函数。 Atest spy可以是匿名函数,也可以包装现有函数。

取自:http://sinonjs.org/docs/

For Minitest我们可以使用宝石spy.

After 安装, and 包括在我们的测试环境中,测试可以重新安排如下:

require 'minitest/autorun'
require 'spy/integration'
require 'ostruct' # (1)
require './lib/under_test'

class TestUnderTest < Minitest::Test
  def test_get_request
    mock_json = '{"json":[{"element":"value"}]}'
    test_uri = URI('https://www.example.com/api/v1.0?attr=value&format=json')

    open_spy = Spy.on_instance_method(Kernel, :open) # (2)
                  .and_return { OpenStruct.new(read: mock_json) } # (1)

    @under_test = UnderTest.new

    assert_equal @test_under.get_request(test_uri), mock_json
    assert open_spy.has_been_called_with?(test_uri) # (3)
  end
end

(1):因为鸭子打字根据 Ruby 的本质,您实际上不需要在测试中提供在应用程序的非测试运行中创建的确切对象。

让我们看看您的UnderTest class:

class UnderTest
  def get_request(uri)
    open(uri).read
  end
end

实际上,open在“生产”环境中可以返回实例Tempfile, which quacks用方法read。然而在你的“测试”环境中,当“存根”,您不需要提供类型的“真实”对象Tempfile。提供就够了anything, that quacks就像一个。

在这里我使用了开放结构, 构建某物,这将响应read信息。让我们仔细看看:

require 'ostruct'
tempfile = OpenStruct.new(read: "Example output")
tempfile.read # => "Example output"

在我们的测试用例中,我们提供minimal代码量,使测试通过。我们不关心其他Tempfile方法,因为我们的测试仅依赖于read.

(2):我们正在创建一个spy on open中的方法Kernel模块,这可能会令人困惑,因为我们需要OpenURI模块。当我们尝试时:

Spy.on_instance_method(OpenURI, :open)

它抛出异常,即

NameError: undefined method `open' for module `OpenURI'

事实证明,open方法附于提到的Kernel module.

此外,我们使用以下代码定义方法调用将返回的内容:

and_return { OpenStruct.new(read: mock_json) }

当我们的测试脚本执行时,@test_under.get_request(test_uri)被执行,它注册了open方法调用及其论据 on our spy目的。这是我们可以断言的(3).

测试可能出错的地方

好的,现在我们已经看到我们的脚本运行没有任何问题,但我想强调一下如何断言我们的示例spy可能会失败。

让我们稍微修改一下测试:

class TestUnderTest < Minitest::Test
  def test_get_request
    open_spy = Spy.on_instance_method(Kernel, :open)
                  .and_return { OpenStruct.new(read: "whatever") }

    UnderTest.new.get_request("http://google.com")

    assert open_spy.has_been_called_with?("http://yahoo.com")
  end
end

运行时会失败,并显示类似以下内容:

  1) Failure:
TestUnderTest#test_get_request [test/lib/test_under_test.rb:17]:
Failed assertion, no message given.

我们已经打电话给我们的get_request, with "http://google.com“,但断言如果spy注册电话为“http://yahoo.com“ 争论。

这证明了我们的spy按预期工作。

这是很长的答案,但我试图提供最好的解释,但我不希望所有事情都清楚 - 如果您有任何问题,我非常乐意提供帮助,并相应地更新答案!

祝你好运!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Minitest 惯用地模拟 OpenURI.open_uri 的相关文章

随机推荐

  • 设置用双引号括起来的单词的 CSS

    这是我的问题的后续问题如果代码包含保留字 则设置代码的 CSS 我正在尝试做什么 如果某些代码有引号或双引号 我想将字体颜色设置为红色和粗体 前任 System out println Hello world 应该将 Hello world
  • 如何使 PageView.Builder() 滚动动画从滞后变得极其流畅 - Flutter

    我使用 PageView Builder 来构建由基本文本小部件数组提供的小部件 但在调试模式下 动画感觉非常滞后 在发布或分析模式下 动画仍然滞后 但少了很多 有什么方法可以完全消除使用PageView时的动画滞后现象 这是我的代码 im
  • 如何从另一台计算机连接到 SQL Server?

    我想使用 SQL Server 2005 从家里连接到另一台 PC 我查看了 msd 但在连接之前它说我应该连接到另一台计算机 使用计算机管理但没有成功 我只能连接到我的工作组中的计算机 谢谢 路易莎 免责声明这只是一些可能对任何人都有帮助
  • 提取C/C++函数原型

    我想做这个 extract prototypes file1 c file2 cpp file3 c 并让任何脚本 程序打印给定 C C 文件中定义的所有函数的函数原型的良好列表 它必须很好地处理多行声明 有没有一个程序可以完成这项工作 越
  • Python 的 eval() 在不受信任的字符串上的安全性?

    如果我使用 eval 评估 Python 字符串 并且有一个类似以下的类 class Foo object a 3 def bar self x return x a 如果我不信任该字符串 会有哪些安全风险 尤其 Is eval strin
  • 计算不同数字数量的省时方法

    get number 返回一个整数 我将调用它 30 次并计算返回的不同整数的数量 我的计划是将这些数字放入std array
  • C++ 在编译时获取月份作为数字

    我有一个 C 项目 必须打印修订字符串 修订字符串是公司指定的 协议包括构建时间 yyyy mm dd 我过去常常将其指定为构建系统中的宏 但这不再是一个选项 因为会弄乱预编译头 在增量构建中 当日期发生变化时 我试图通过从编译器获取构建日
  • 表达式引擎 - 完全删除index.php

    一段时间以来 我一直在 htaccess 文件中使用以下代码 以使 EE URL 正常工作 而无需在 URL 中使用 index php 我发现 虽然我从爬行工具中收到一些报告 但我得到了重复的内容 如 lorem ipsum 也以 ind
  • R 插入符 / rfe 变量选择 Factor() AND NA

    我有一个数据集NAs慷慨地撒在各处 此外 它还有需要的列factors 我正在使用rfe 函数从caret包来选择变量 看来functions 论证中rfe using lmFuncs适用于具有 NA 的数据 但不适用于因子变量 而rfFu
  • 在 C# 中使用信号量

    嗨 我正在尝试使用Semaphore在我的应用程序中 我已经这样声明了 class MyThread public Thread Thrd static Semaphore sem new Semaphore 2 2 public MyTh
  • 关于 Mongoid/MongoDB 标签树结构的建议

    我正在寻找有关如何构建此数据模型的标签部分的一些建议 这是它的简化版本 一个站点有许多帖子 关系关联 mongoid 中的references many 站点有一个标签树 帖子有一系列标签 网站标签的子集 顺序无关紧要 我关心的用例是 快速
  • 尝试在 raspbian wheezy 上构建 opencv-2.4.10 时未声明 SIZE_MAX

    我正在尝试在我的 Raspberry Pi model B 喘息 上构建 opencv 2 4 10 如下这些说明但出现以下错误 解决这个问题的最佳方法是什么 14 Building CXX object modules highgui C
  • 使用socket处理生物指纹考勤机

    我正在尝试使用 Java 程序连接生物识别指纹考勤设备 我使用的设备是Biocom指纹考勤系统 然而 我正在搜索和阅读相关内容 我发现可以根据设备类型使用 SDK 这很难 不符合逻辑 而且 它不是全局解决方案 我研究了如何使用指纹设备连接
  • 使用java Scanner获取字符串中的标记数量

    Java中有没有办法获取Method Scanner获取到的字符串中token的个数 我的意思是 我可以使用s sc nextLine 获取字符串形式的输入行 但在这个字符串上我不能使用lenght 方法因为它给了我字符总数 我认为 是否有
  • x86 段寄存器在现代 CPU 和操作系统上有特殊含义/用途吗?

    从 16 位到 32 位再到 64 位 x86 CPU 历代都有各种棘手的模式和内存分段 如今 现代操作系统在现代操作模式下使用现代 CPU 您不必担心内存段 但您仍然可以在现代 CPU 上的旧操作系统上运行旧应用程序 在这种情况下 我假设
  • 如何解决 python requests SSL 和 proxy 错误?

    当发送带有身份验证的请求时 我收到 requests exceptions SSLError 错误 您可以在下面看到该错误 proxies https http user pass ip port url https httpbin org
  • WindowsError:[错误 740] 即使禁用 UAC 后,请求的操作也需要提升

    我已禁用 UAC 并在 python 中运行我的脚本 command abcd exe subprocess Popen command stdout subprocess PIPE stderr subprocess PIPE commu
  • JPA 中按截断日期分组

    我需要帮助 我需要建立规范 SELECT date trunc day start time FROM Example GROUP BY date trunc day start time PostgreSQL 我有代码 CriteriaB
  • java中将字符串转换为java.util.date格式

    我有一个这样的字符串 Thu Oct 07 11 31 50 IST 2010 我想将其转换为精确的日期时间格式以将其存储在 SQL 中 我熟悉许多字符串到日期的转换 如下所示 String dateString 2001 03 09 Si
  • 使用 Minitest 惯用地模拟 OpenURI.open_uri

    我有调用的代码OpenURI open uri我想确认调用中使用的 URI 因此存根对我不起作用 但也拦截调用 我希望不必抽象出对OpenURI open uri仅用于测试目的 我想出的东西似乎冗长且过于复杂 测试下 rb require