对于这个问题,测试间谍可能是要走的路:
test spy 是一个函数,它记录所有调用的参数、返回值、this 的值和抛出的异常(如果有的话)。 测试间谍可以是匿名函数,也可以包装现有函数。
取自:http://sinonjs.org/docs/
对于Minitest,我们可以使用gem spy。
在我们的测试环境中installing和including之后,测试可以重新安排如下:
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):由于duck typing Ruby 的性质,您实际上不需要在测试中提供将在应用程序的非测试运行中创建的确切对象。
让我们看看你的UnderTest 类:
class UnderTest
def get_request(uri)
open(uri).read
end
end
事实上,“生产”环境中的open 可以返回Tempfile 的实例,它与read 方法嘎嘎作响。但是在您的“测试”环境中,当“存根”时,您不需要提供Tempfile 类型的“真实”对象。提供任何东西,嘎嘎声 就足够了。
在这里,我使用OpenStruct 的力量来构建一些东西,它将响应read 消息。让我们仔细看看:
require 'ostruct'
tempfile = OpenStruct.new(read: "Example output")
tempfile.read # => "Example output"
在我们的测试用例中,我们提供最少数量的代码,以使测试通过。我们不关心其他Tempfile 方法,因为我们的测试只依赖于read。
(2):我们在Kernel 模块中的open 方法上创建spy,这可能会造成混淆,因为我们需要OpenURI 模块。当我们尝试时:
Spy.on_instance_method(OpenURI, :open)
它抛出异常,
NameError: undefined method `open' for module `OpenURI'
原来open方法附加到提到的Kernel模块。
另外,我们用下面的代码定义方法调用返回的内容:
and_return { OpenStruct.new(read: mock_json) }
当我们的测试脚本执行时,@test_under.get_request(test_uri) 被执行,它在我们的spy 对象上注册open 方法调用及其参数。这是我们可以通过(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.
我们使用“http://google.com”调用了我们的get_request,但断言如果spy 使用“http://yahoo.com”参数注册了调用。
这证明我们的spy 可以正常工作。
这是一个很长的答案,但我试图提供最好的解释,但我不希望所有事情都清楚 - 如果您有任何问题,我非常乐意提供帮助,并相应地更新答案!
祝你好运!