4

I have a method I want to test that is being called with a particular object. However, identifying this object is somewhat complex because I'm not interested in a particular instance of the object, but one that conforms to certain conditions.

For example, my code might be like:

some_complex_object = ComplexObject.generate(params)
my_function(some_complex_object)

And in my test I want to check that

test_complex_object = ComplexObject.generate(test_params)
subject.should_receive(:my_function).with(test_complex_object)

But I definitely know that ComplexObject#== will return false when comparing some_complex_object and test_complex_object because that is desired behavior (elsewhere I rely on standard == behavior and so don't want to overload it for ComplexObject).

I would argue that it's a problem that I find myself needing to write a test such as this, and would prefer to restructure the code so that I don't need to write such a test, but that's unfortunately a much larger task that would require rewriting a lot of existing code and so is a longer term fix that I want to get to but can't do right now within time constraints.

Is there a way with Rspec to be able to do a more complex comparison between arguments in a test? Ideally I'd like something where I could use a block so I can write arbitrary comparison code.

2

1 Answer 1

5

See https://www.relishapp.com/rspec/rspec-mocks/v/2-7/docs/argument-matchers for information on how you can provide a block to do arbitrary analysis of the arguments passed to a method, as in:

expect(subject).to receive(:my_function) do |test_complex_object|
   # code setting expectations on test_complex_object
end

You can also define a custom matcher which will let you evaluate objects to see if that satisfy the condition, as described in https://www.relishapp.com/rspec/rspec-expectations/v/2-3/docs/custom-matchers/define-matcher

Sign up to request clarification or add additional context in comments.

1 Comment

since i originally wrote this question i've switched in some places to rspec 3, which also supports a nestable satisfy matcher that can accept arbitrary blocks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.