vendredi 6 mars 2015

How can I mock something that "does not implement" a particular method?

The Background:


I'm trying to use cucumber to do some test-driven (or behavior-driven) development around an interface to AWS, in ruby.


So, I have a step definition that looks like this:



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


Where @mock was previously set using:



@mock = instance_double(AWS::AutoScaling::Client)


And where I invoke this step definition with a feature line like:



And the mock object should have had :update_auto_scaling_group called, setting "auto_scaling_group_name" to "Some-test-value"


When that step gets run, it gets the following error (leaving out the full error, as I believe this is the most relevant part):



AWS::AutoScaling::Client does not implement: update_auto_scaling_group (RSpec::Mocks::MockExpectationError)


I see that indeed, the checks that RSpec runs (as traced back from where the RSpec::Mocks::MockExpectationError gets thrown) are at least correctly reporting the information that they get from the class:



[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


And yet, if we ask an actual instance, it lets us know that this is a method it would respond to:



[6] pry(main)> x = klass.new
=> #<AWS::AutoScaling::Client::V20110101>
[7] pry(main)> x.respond_to? "update_auto_scaling_group"
=> true


Even while it doesn't say that about just anything:



[8] pry(main)> x.respond_to? "bogus"
=> false


First questions:


So... is this a bug in the AWS::AutoScaling::Client code (or really, probably here), for not defining the methods in a way that the extant checks ({public,private,protected}_method_defined?) would come back true?


Or perhaps a bug in RSpec's "doubles", for not doing all the checking it could do to try to find out that this is indeed a method that's callable in an instance of that class?


Or perhaps it's simply something that I'm doing wrong here? Other?


More generally:


How can I write tests for the code I'm writing, to ensure that it's making calls to what will be an AWS::AutoScaling::Client instance, with the correct parameters (as defined in several checks that I have)? Are there alternate ways I can write my step definitions that would make this work? Alternative ways to create my mock objects? Other?


Aucun commentaire:

Enregistrer un commentaire