You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Just started using RR a couple days ago, so this may be a little dumb, but I had some surprises with the behavior of the "mock!" and "stub!" methods which I will try to summarize here:
my_stub_object = stub!.hello.subject
my_stub_object.hello # => works
Ok. Second surprise, then, is that here no "subject()" call needed:
stub(object).foo {stub!.bar}
object.foo.bar # => works
This is surprising because "stub(object).foo {something}" means "stub the foo method on object to return something", and that "something" is "stub!.bar". From the first example I would expect "stub!.bar" to return something that will raise a NoMethodError if I send it a "bar" message, unless I instead write it as "stub!.bar.subject". But no, it works.
(Evidently some magic is going on there, either in the stub! method defined within the context of the block, or the surrounding code which yields to the block itself... haven't dug into it yet.)
It's not clear why you can do:
stub(a).foo.stub!.bar.stub!.baz
a.foo.bar.baz # => works
But not:
a = stub!.foo.stub!.bar.stub!.baz
a.foo.bar.baz # => NoMethodError (undefined method 'foo')
The surprise here is that "stub!" calls can be chained, but not if the "stub!" call is the first link in the chain.
Likewise, you'll fail if you try this:
a = stub!.foo.subject
a.stub!.bar # => NoMethodError (undefined method 'stub!')
Or this:
a = stub!.foo.stub!.bar.stub!.baz.subject
a.foo.bar.baz # => NoMethodError (undefined method 'foo')
So I understand that "stub!()" is generally returning a double definition instance so that additional calls can be chained onto it, but I'm wondering if some of these little surprises could be avoided.
For example, could the first surprise be avoided by having:
my_stub_object = stub!.hello
Return the subject? (Obviously the subject itself would need methods like "stub!" itself mixed into it in order to permit chaining.) Or a version of double definition that responds to the "hello" method?
It seems that fixing that would also fix this:
a = stub!.foo.stub!.bar.stub!.baz
Because at each step of the chain, including the first one, we would return an object that understood both the stubbed method and other chaining methods such as "stub!" itself. (Not sure whether this would open up a can of worms in the case of "mock!").
Anyway, like I said, sorry if these are all dumb questions, but this is really the first place in RR where I've found myself surprised by its behavior. Everywhere else the interface has been rather intuitive.
Cheers,
Wincent
The text was updated successfully, but these errors were encountered:
+1. Those are real inconsistencies! What's even worse - there is almost no mention of this in the README. I've wasted a good deal of time fighting with rr syntax.
Sorry for the late reply on this, I am starting to whip this thing into shape. I tend to use obj = Object.new; stub(obj).whatever because I can never figure out how #stub! works. I don't really have an immediate answer for this so I'll have to look into it. I can at least add something to the README, yes.
Just started using RR a couple days ago, so this may be a little dumb, but I had some surprises with the behavior of the "mock!" and "stub!" methods which I will try to summarize here:
First surprise is that this doesn't work:
So, the docs tell us about the subject() method:
Ok. Second surprise, then, is that here no "subject()" call needed:
This is surprising because "stub(object).foo {something}" means "stub the foo method on object to return something", and that "something" is "stub!.bar". From the first example I would expect "stub!.bar" to return something that will raise a NoMethodError if I send it a "bar" message, unless I instead write it as "stub!.bar.subject". But no, it works.
(Evidently some magic is going on there, either in the stub! method defined within the context of the block, or the surrounding code which yields to the block itself... haven't dug into it yet.)
It's not clear why you can do:
But not:
The surprise here is that "stub!" calls can be chained, but not if the "stub!" call is the first link in the chain.
Likewise, you'll fail if you try this:
Or this:
So I understand that "stub!()" is generally returning a double definition instance so that additional calls can be chained onto it, but I'm wondering if some of these little surprises could be avoided.
For example, could the first surprise be avoided by having:
Return the subject? (Obviously the subject itself would need methods like "stub!" itself mixed into it in order to permit chaining.) Or a version of double definition that responds to the "hello" method?
It seems that fixing that would also fix this:
Because at each step of the chain, including the first one, we would return an object that understood both the stubbed method and other chaining methods such as "stub!" itself. (Not sure whether this would open up a can of worms in the case of "mock!").
Anyway, like I said, sorry if these are all dumb questions, but this is really the first place in RR where I've found myself surprised by its behavior. Everywhere else the interface has been rather intuitive.
Cheers,
Wincent
The text was updated successfully, but these errors were encountered: