对于这个问题,测试间谍可能是可行的方法:
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
按预期工作。
这是很长的答案,但我试图提供最好的解释,但我不希望所有事情都清楚 - 如果您有任何问题,我非常乐意提供帮助,并相应地更新答案!
祝你好运!