[rspec-devel] [ rspec-Feature Requests-12895 ] mocks with inline stubs

noreply at rubyforge.org noreply at rubyforge.org
Sat Sep 1 09:58:10 EDT 2007


Feature Requests item #12895, was opened at 2007-08-08 00:51
You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=3152&aid=12895&group_id=797

Category: None
Group: None
>Status: Closed
Priority: 3
Submitted By: Scott Taylor (smtlaissezfaire)
Assigned to: Nobody (None)
Summary: mocks with inline stubs

Initial Comment:

Oftentimes I find myself with a setup like this:

@mock = mock Object
Object.stub!(:new).and_return @mock
@mock.stub!(:method_one).and_return "foo"
@mock.stub!(:method_two).and_return "bar"

After several mock objects + their stubs in one setup/before block, this can get quite hard to read.  This code could be abstracted into a helper method, but I find that generally does not help the readability of the situation.

Would the following solve the problem:

obj = mock Object do |o|
  Object.stub!(:new).and_return o
  o.stub!(:method_one).and_return "foo"
  o.stub!(:method_two).and_return "bar"
end

or with an implicit receiver:

obj = mock Object do
  stub!(:method_one).and_return "foo"
  stub!(:method_two).and_return "bar"
end

I think this would go along way to making before/setup blocks easier to read, if, for no other reason, then the convention of pretty prettying.  WDYT?

----------------------------------------------------------------------

>Comment By: David Chelimsky (dchelimsky)
Date: 2007-09-01 13:58

Message:
I'm going to reject this one. You can either do this:

Object.stub!(:new).and_return(
  stub("object",
    :method_one => "foo",
    :method_two => "bar
  )
)

or try RR.

----------------------------------------------------------------------

Comment By: Brian Takita (btakita)
Date: 2007-08-08 05:25

Message:
Yes RR does support that type of syntax. I've been meaning
to make a blog post that has a tutorial.

Lets say you want to stub User.new. In RR, you can say:

# This mocks each instance of User with the expectations
that method_one and method_two will be called once and
return "foo" and "bar".
mock.instance_of(User) do |o|
  o.method_one {"foo"}
  o.method_two {"bar"}
end

or alternatively:

# This allows the real call to User.new and intercepts the
return value
stub.probe(User).new do |user|
  mock(user).method_one {"foo"}
  mock(user).method_two {"bar"}
  user
end

Of course, literally stubbing Object.new will cause a stack
error on any of Ruby's mock frameworks.

----------------------------------------------------------------------

Comment By: David Chelimsky (dchelimsky)
Date: 2007-08-08 03:56

Message:
There's already a shorthand for this:

Object.stub!(:new).and_return(
  stub(
    "object",
    :method_one => "foo",
    :method_two => "bar
  )
)

To be honest, I find the example you gave at the beginning much easier to grok what's going on than the alternatives you suggest. Although, perhaps the first one would be a bit cleaner like this:

Object.stub!(:new).and_return(mock(Object) do |o|
  o.stub!(:method_one).and_return "foo"
  o.stub!(:method_two).and_return "bar"
end)

You might be interested in Brian Takita's new framework called RR. I'm pretty sure it let's you this:

obj = mock(Object) do |o|
  o.method_one { "foo" }
  o.method_two { "bar" }
end

Brian - if you read this please confirm or deny.

I'm inclined to close this, but I'll leave it open for others to comment.

Comments?

----------------------------------------------------------------------

You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=3152&aid=12895&group_id=797


More information about the rspec-devel mailing list