Skip to content

Commit

Permalink
Add a sketch implementation of args diffing
Browse files Browse the repository at this point in the history
Related #434. This uses the differ that is now in RSpec support to
perform argument diffing when arguments don't match.

Things worth noting/still to do:

* Special case behaviour needs to be added for the no arguments matcher
  and the any arguments matcher, at the moment something like this:
       @@ -1,2 +1,2 @@
       -[#<RSpec::Mocks::ArgumentMatchers::NoArgsMatcher:0x000001024ec728>]
       +[{:bees=>:foo}]
  gets printed, and that's obviously not great.
* Need to work out what to do in the "similar args" case where there are
  potientially multiple calls. I think the best thing to do would be to
  would be to only diff if there's one call.

There's some refactoring that could be done here but I want to finish
implementing the "similar args" implementation before I do that so that
I'm sure that I'm refactoring the right thing.
  • Loading branch information
Sam Phippen committed Sep 4, 2014
1 parent f4293ba commit 24b1685
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 11 deletions.
29 changes: 19 additions & 10 deletions lib/rspec/mocks/error_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,29 @@ def raise_unexpected_message_error(message, *args)
def raise_unexpected_message_args_error(expectation, *args)
expected_args = format_args(*expectation.expected_args)
actual_args = format_received_args(*args)
__raise "#{intro} received #{expectation.message.inspect} with " \
"unexpected arguments\n expected: #{expected_args}\n" \
" got: #{actual_args}"
diff = diff_message(expectation.expected_args, args)
message = "#{intro} received #{expectation.message.inspect} #{unexpected_arguments_message(expected_args, actual_args)}"
message << " #{diff}" unless diff.empty?
__raise message
end

# @private
def raise_missing_default_stub_error(expectation, *args)
expected_args = format_args(*expectation.expected_args)
actual_args = format_received_args(*args)
__raise "#{intro} received #{expectation.message.inspect} with " \
"unexpected arguments\n expected: #{expected_args}\n" \
" got: #{actual_args}\n Please stub a default value " \
"first if message might be received with other args as well. \n"
diff = diff_message(expectation.expected_args, args)
message = "#{intro} received #{expectation.message.inspect} #{unexpected_arguments_message(expected_args, actual_args)}"
message << " #{diff}" unless diff.empty?
message << "\n Please stub a default value first if message might be received with other args as well. \n"
__raise message
end

# @private
def raise_similar_message_args_error(expectation, *args_for_multiple_calls)
expected_args = format_args(*expectation.expected_args)
actual_args = args_for_multiple_calls.map { |a| format_received_args(*a) }.join(", ")
__raise "#{intro} received #{expectation.message.inspect} with " \
"unexpected arguments\n expected: #{expected_args}\n" \
" got: #{actual_args}"
actual_args = args_for_multiple_calls.collect {|a| format_received_args(*a)}.join(", ")
__raise "#{intro} received #{expectation.message.inspect} #{unexpected_arguments_message(expected_args, actual_args)}"
end

# rubocop:disable Style/ParameterLists
Expand Down Expand Up @@ -194,6 +195,14 @@ def self.raise_double_negation_error(wrapped_expression)

private

def unexpected_arguments_message(expected_args_string, actual_args_string)
"with unexpected arguments\n expected: #{expected_args_string}\n got: #{actual_args_string}"
end

def diff_message(expected_args, actual_args)
RSpec::Support::Differ.new(:color => true).diff(actual_args, expected_args)
end

def intro
if @name
"Double #{@name.inspect}"
Expand Down
2 changes: 1 addition & 1 deletion spec/rspec/mocks/double_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def @double.method_with_default_argument(arg={}); end
expect {
@double.method_with_default_argument(nil)
verify @double
}.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" received :method_with_default_argument with unexpected arguments\n expected: ({})\n got: (nil)")
}.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" received :method_with_default_argument with unexpected arguments\n expected: ({})\n got: (nil) \e[0m\n\e[0m\e[34m@@ -1,2 +1,2 @@\n\e[0m\e[31m-[{}]\n\e[0m\e[32m+[nil]\n\e[0m")
end
end

Expand Down

0 comments on commit 24b1685

Please sign in to comment.