我正在尝试使用黄瓜围绕AWS的接口进行一些测试驱动(或行为驱动)开发,在ruby中。
所以,我有一个步骤定义,如下所示:
Then(/^the mock object should have had :(.*?) called, setting "(.*?)" to "(.*?)"$/) do |method, param, value|
expect(@mock).to receive(method.to_sym).with(hash_including(param, value))
end
以前使用以下设置@mock
的位置:
@mock = instance_double(AWS::AutoScaling::Client)
我用以下功能行调用此步骤定义:
And the mock object should have had :update_auto_scaling_group called, setting "auto_scaling_group_name" to "Some-test-value"
当该步骤运行时,它会收到以下错误(遗漏完整错误,因为我认为这是最相关的部分):
AWS::AutoScaling::Client does not implement: update_auto_scaling_group (RSpec::Mocks::MockExpectationError)
我确实看到checks that RSpec runs(追溯from where the RSpec::Mocks::MockExpectationError
gets thrown)至少正确地报告了他们从班级获得的信息:
[1] pry(main)> require 'aws-sdk'
=> true
[2] pry(main)> klass = AWS::AutoScaling::Client
=> AWS::AutoScaling::Client
[3] pry(main)> klass.public_method_defined? "update_auto_scaling_group"
=> false
[4] pry(main)> klass.private_method_defined? "update_auto_scaling_group"
=> false
[5] pry(main)> klass.protected_method_defined? "update_auto_scaling_group"
=> false
然而,如果我们问一个实际的实例,它会让我们知道这是一个它会响应的方法:
[6] pry(main)> x = klass.new
=> #<AWS::AutoScaling::Client::V20110101>
[7] pry(main)> x.respond_to? "update_auto_scaling_group"
=> true
即使它没有说任何事情:
[8] pry(main)> x.respond_to? "bogus"
=> false
所以...这是the AWS::AutoScaling::Client code(或者真的,可能是here)中的一个错误,因为没有以现有检查({public,private,protected}_method_defined?
)来定义方法回到真的吗?
或许是RSpec的“双打”中的一个错误,因为没有做所有的检查,试图找出这确实是一个可以在该类的实例中调用的方法?
或许这只是我在这里做错的事情?其他
我如何为我正在编写的代码编写测试,以确保它使用正确的参数(如我在几个检查中定义的那样)调用AWS::AutoScaling::Client
实例。我是否有其他方法可以编写可以使其工作的步骤定义?创建我的模拟对象的其他方法?其他
答案 0 :(得分:1)
我找到了一种动态混合模拟
所需方法的方法您可以使用空方法执行此操作,然后将它们存根,或者只在stubin中包含存根
Sub ReplaceValues
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim rows1 As Long
Dim rows2 As Long
Dim row1 As Long
Dim row2 As Long
Set ws1 = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")
rows1 = ws1.Range("A" & ws1.Rows.Count).End(xlUp).Row
rows2 = ws2.Range("A" & ws2.Rows.Count).End(xlUp).Row
For row1 = 1 To rows1
For row2 = 1 To rows2
ws1.Cells(row1, 1).Value = Replace(ws1.Cells(row1, 1).Value, _
ws2.Cells(row2, 1).Value, _
ws2.Cells(row2, 2).Value)
Next
Next
End Sub
答案 1 :(得分:0)
它只是在实例化时/之后添加方法。它非常合法,所有红宝石类/对象都是开放的。
正确答案 - 您不希望使用开放类和对象测试您尝试使用duck-typed语言测试的内容。它没有意义。
答案 2 :(得分:0)
适用于Ruby的第1版AWS开发工具包使用#method_missing
作为构建和发送请求的委托。客户端响应的方法在API定义中定义。这样可以消除样板代码,但如果您试图在运行时反映可用的方法,则会导致问题。
选项A:使用常规double并在测试双精度上应用断言。
选项B:通过AWS.stub使用SDK的模拟功能!启用存根时,构造的所有客户端都将响应其常规方法,但将返回虚拟响应(空哈希和数组)。此方法提供了指定从存根返回的数据的有用功能。您甚至可以创建存根响应,以明确从断言返回。
选择B:
# use `:stub_requests` or call Aws.stub!
as = AWS::AutoScaling::Client.new(:stub_requests: true)
# validates parameters as normal, but returns empty response data
as.update_auto_scaling_group(auto_scaling_group_name: 'name')
#=> {}
# You can access the stub response for any operation by name:
stub = as.stub_for(:describe_auto_scaling_groups)
stub.data[:auto_scaling_group_names] = ["Group1", "Group2"]
# Now calling that operation will return the stubbed data
resp = as.describe_auto_scaling_groups
resp.auto_scaling_group_names
#=> ['Group1', 'Group2']
如果需要断言对客户端调用方法,则可以正常执行,返回存根响应:
expect(@client).to receive(:describe_auto_scaling_groups).
with(hash_including(param, value)).
and_return(@client.stub_for(:describe_auto_scaling_groups))