[rspec-devel] Partially mocked objects that define == blow up when another mock exists

David Chelimsky dchelimsky at gmail.com
Mon Oct 1 18:47:14 EDT 2007


On 10/1/07, Pat Maddox <pergesu at gmail.com> wrote:
> One of my coworkers wrote a class that defines == to have simple value
> object semantics.  One of our specs partially stubs the value object.
> A change in the last week or so broke it.  Here's the setup:
>
> stub("existing mock", :foo => :foo)
> class ValueObject
>   attr_reader :val
>
>   def initialize(val)
>     @val = val
>   end
>
>   def ==(other)
>     @val == other.val
>   end
> end
>
> @obj = ValueObject.new :bar
> @obj.stub!(:some_method)  # blows up with undefined method on
> #<Spec::Mocks::Proxy>
>
> Now, this was easily fixed with changing == to
>
> def ==(other)
>   other.responds_to?(:val) && @val == val
> end
>
> which imo is better anyway, at least in this particular case.  His
> argument was, "but we're never going to pass in an object of a
> different class" in which case he should probably check the other
> object's class just to make sure.
>
> Anyway, I was interested in why this failed, because the error message
> wasn't very helpful.
>
> The problem is that in Spec::Mocks::Space#add it calls mocks.include?.
>  Internally, Ruby uses == in include?, which in this case blows up.
>
> I've got two ideas on this.  The first is to check for object identity
> using equal?.  #add becomes:
>
> def add(obj)
>   mocks << obj unless mocks.detect {|m| m.equal? obj}
> end
>
> This way people can write the first version of == with no problems.
>
> Another option is to inform them of duck typing, and that they'll want
> to either use respond_to or check for the object's class.
>
> The first way is less intrusive, and I think I would prefer it solely
> on that merit.  I don't hate the other way though, and that's just as
> trivial to implement.  Just rescue NoMethodError in #add with a link
> to some duck typing page.
>
> Here's a patch for the .equal? version: http://pastie.caboo.se/102619
> I opted not to put it in the tracker because I wanted to generate some
> discussion first.  Plus there are a lot of patches that are just
> chilling there and I don't know if anyone's looking at them :)

As luck would have it, I just ran into this exact problem. I think
your solution is sound. Unless anyone else barks "nay", I'd say go
ahead and submit the patch to the tracker and I'll apply it.

Cheers,
David

>
> Pat
> _______________________________________________
> rspec-devel mailing list
> rspec-devel at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-devel
>


More information about the rspec-devel mailing list