New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the new expectation syntax for mocks #153

Closed
iain opened this Issue Jun 15, 2012 · 128 comments

Comments

Projects
None yet
@iain

iain commented Jun 15, 2012

If you want to use the new expectation syntax, then the current mock syntax will look out of place.

That's why I propose we introduce the following matcher:

expect(object).to receive(:message).with(arg1, arg2)

Some considerations:

  • This would not be usable without rspec-expectations. I don't know how problematic this is, but it is a feature of rspec-mocks.
  • I don't know if we should change stub. It's not an expectation/assertion, so I don't think it needs to change.
@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jun 15, 2012

Member

This would help solve #116, as it's essentially the same delegate issue we've now dealt with in rspec-expectations.

This would not be usable without rspec-expectations. I don't know how problematic this is, but it is a feature of rspec-mocks.

I can think of some ways to make this work w/o depending on rspec-expectations using feature detection.

Member

myronmarston commented Jun 15, 2012

This would help solve #116, as it's essentially the same delegate issue we've now dealt with in rspec-expectations.

This would not be usable without rspec-expectations. I don't know how problematic this is, but it is a feature of rspec-mocks.

I can think of some ways to make this work w/o depending on rspec-expectations using feature detection.

@justinko

This comment has been minimized.

Show comment
Hide comment
@justinko

justinko Jun 18, 2012

Contributor

Basically, RR[1] provides the cleanest solution to this issue. I would like to see something like this in rspec-mocks:

stub(User).all { the_users } # uses `method_missing`
stub(User, :all) { the_users } # does not use `method_missing`

mock(User).all # an "expectation" that `all` will be called

double('the user') # same as the current `double`

To utilize stub and mock as in the example above, it would cause a massive breaking change. Totally worth it IMO.

/cc @dchelimsky

1.) https://github.com/btakita/rr

Contributor

justinko commented Jun 18, 2012

Basically, RR[1] provides the cleanest solution to this issue. I would like to see something like this in rspec-mocks:

stub(User).all { the_users } # uses `method_missing`
stub(User, :all) { the_users } # does not use `method_missing`

mock(User).all # an "expectation" that `all` will be called

double('the user') # same as the current `double`

To utilize stub and mock as in the example above, it would cause a massive breaking change. Totally worth it IMO.

/cc @dchelimsky

1.) https://github.com/btakita/rr

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jun 18, 2012

Member

I thought about this a bit more, and I came up an idea that's similar, but avoids the massive breakage:

stubbing(User, :all) do
  the_users
end

mocking(User, :all)

The "-ing" forms aren't taken up by anything yet, and read nicely when used with the block form. It looks a little weird when you're just mocking it w/o an implementation, though.

The feedback on the recent syntax changes in rspec-expectations have been overwhelmingly positive, and I think the fact that we didn't break anything is a big part of that. I don't think massive breaking change is acceptable at this point, unless we decide to do it in a separate gem (e.g. rspec-better-mocks or whatever).

On a side note, if we can come up with a good solution here, we have the potential to get rspec in a place where the monkey patching it does is very, very minimal. Up to now, RSpec has added the following methods to every object in the system:

  • describe
  • should
  • should_not
  • should_receive
  • should_not_receive
  • stub
  • stub!
  • and maybe some others I'm not thinking of.

should and should_not have been dealt with w/ the expect syntax, and I just fixed rspec core in rspec/rspec-core#638 to no longer add describe to every object. The methods added by rspec-mocks are the last major source of monkey patching ever object, so if we can find a good solution here it would be great :).

Member

myronmarston commented Jun 18, 2012

I thought about this a bit more, and I came up an idea that's similar, but avoids the massive breakage:

stubbing(User, :all) do
  the_users
end

mocking(User, :all)

The "-ing" forms aren't taken up by anything yet, and read nicely when used with the block form. It looks a little weird when you're just mocking it w/o an implementation, though.

The feedback on the recent syntax changes in rspec-expectations have been overwhelmingly positive, and I think the fact that we didn't break anything is a big part of that. I don't think massive breaking change is acceptable at this point, unless we decide to do it in a separate gem (e.g. rspec-better-mocks or whatever).

On a side note, if we can come up with a good solution here, we have the potential to get rspec in a place where the monkey patching it does is very, very minimal. Up to now, RSpec has added the following methods to every object in the system:

  • describe
  • should
  • should_not
  • should_receive
  • should_not_receive
  • stub
  • stub!
  • and maybe some others I'm not thinking of.

should and should_not have been dealt with w/ the expect syntax, and I just fixed rspec core in rspec/rspec-core#638 to no longer add describe to every object. The methods added by rspec-mocks are the last major source of monkey patching ever object, so if we can find a good solution here it would be great :).

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jun 18, 2012

Member

The "ing" idiom suggests to me "scoped within this block" e.g.

stubbing(User, :all => [User.new]) do
  # stub is scoped to this block
end
# that stub is no longer available

I actually have a never-used-lib that uses this syntax for that purpose.

Also, I'd prefer to have a syntax that aligns with the changes to rspec-expectations if we're going to do this. I'd be OK with:

stub(object, :method => value)
stub(object, :method) { lazy_value }
expect(object).to receive(:message)

I would not be OK with:

stub(object).method { lazy_value }
mock(object).method { lazy_value }

This syntax is no more terse than the others, but it is not intention revealing IMO.

Member

dchelimsky commented Jun 18, 2012

The "ing" idiom suggests to me "scoped within this block" e.g.

stubbing(User, :all => [User.new]) do
  # stub is scoped to this block
end
# that stub is no longer available

I actually have a never-used-lib that uses this syntax for that purpose.

Also, I'd prefer to have a syntax that aligns with the changes to rspec-expectations if we're going to do this. I'd be OK with:

stub(object, :method => value)
stub(object, :method) { lazy_value }
expect(object).to receive(:message)

I would not be OK with:

stub(object).method { lazy_value }
mock(object).method { lazy_value }

This syntax is no more terse than the others, but it is not intention revealing IMO.

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jun 18, 2012

Member

@dchelimsky -- I like your thinking here, but won't stub(object, :method => value) be a breaking change? Currently the stub method within an example creates a new test double; here it stubs a method on the given object.

This wouldn't just be a breaking change; this would be an incredibly confusing breaking change. Removing a method, so that users start getting NoMethodErrors is one thing; taking an existing method, and completely changing it's semantics so that it does something entirely different will be far more difficult for users to deal with. They'll get confusing failures and won't have an easy way to scan their code to find the old uses of stub.

Member

myronmarston commented Jun 18, 2012

@dchelimsky -- I like your thinking here, but won't stub(object, :method => value) be a breaking change? Currently the stub method within an example creates a new test double; here it stubs a method on the given object.

This wouldn't just be a breaking change; this would be an incredibly confusing breaking change. Removing a method, so that users start getting NoMethodErrors is one thing; taking an existing method, and completely changing it's semantics so that it does something entirely different will be far more difficult for users to deal with. They'll get confusing failures and won't have an easy way to scan their code to find the old uses of stub.

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jun 18, 2012

Member

@myronmarston STOP MAKING SENSE! :)

Yes, we'll need a new name, but that's the form I want to use: some_new_name(object, :method => value).

One option would be allow (comes from one of the java mock frameworks - can't recall which and google is not my friend today).

Member

dchelimsky commented Jun 18, 2012

@myronmarston STOP MAKING SENSE! :)

Yes, we'll need a new name, but that's the form I want to use: some_new_name(object, :method => value).

One option would be allow (comes from one of the java mock frameworks - can't recall which and google is not my friend today).

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jun 18, 2012

Member

Maybe stub_method(object, :method => value)?

Member

myronmarston commented Jun 18, 2012

Maybe stub_method(object, :method => value)?

@iain

This comment has been minimized.

Show comment
Hide comment
@iain

iain Jun 20, 2012

Is it necessary to change stub at the same time? I know we want to fix the bug for stubbing, but should mocks wait for this?

@myronmarston For some reason I dislike the word method in there. I like the fact that mocks use the vocabulary of sending and receiving messages. Not sure on an alternative though.

iain commented Jun 20, 2012

Is it necessary to change stub at the same time? I know we want to fix the bug for stubbing, but should mocks wait for this?

@myronmarston For some reason I dislike the word method in there. I like the fact that mocks use the vocabulary of sending and receiving messages. Not sure on an alternative though.

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jun 20, 2012

Member

Any objections to allow? Then we'd have:

allow(object, :method => value)
allow(object, :method) { lazy_value }
expect(object).to receive(:message)
Member

dchelimsky commented Jun 20, 2012

Any objections to allow? Then we'd have:

allow(object, :method => value)
allow(object, :method) { lazy_value }
expect(object).to receive(:message)
@iain

This comment has been minimized.

Show comment
Hide comment
@iain

iain Jun 20, 2012

Looks great!

iain commented Jun 20, 2012

Looks great!

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jun 20, 2012

Member

Any objections to allow?

A couple concerns I have:

  • allow makes sense on a pure mock object, because you'll get errors unless you mock or allow every method called on the object. But it makes very little sense on real objects. You're always allowed to call every method on a real object. When you're stubbing a method on a real object in order to force it's return value, allow doesn't really fit.
  • It seems like a shard departure from the current terminology employed by rspec-mocks. But maybe that's a good thing.

Here's another idea: respond_to:

respond_to(object, :method => value)
respond_to(object, :method) { lazy_value }
respond_to(object, :method).with(some_argument) { lazy_value }

When you stub a method, you're setting how an object responds to a particular message.

Member

myronmarston commented Jun 20, 2012

Any objections to allow?

A couple concerns I have:

  • allow makes sense on a pure mock object, because you'll get errors unless you mock or allow every method called on the object. But it makes very little sense on real objects. You're always allowed to call every method on a real object. When you're stubbing a method on a real object in order to force it's return value, allow doesn't really fit.
  • It seems like a shard departure from the current terminology employed by rspec-mocks. But maybe that's a good thing.

Here's another idea: respond_to:

respond_to(object, :method => value)
respond_to(object, :method) { lazy_value }
respond_to(object, :method).with(some_argument) { lazy_value }

When you stub a method, you're setting how an object responds to a particular message.

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jun 20, 2012

Member

Unfortunately, respond_to(object, :method).with(:foo) sounds like "respond to object.method by returning foo"

Member

dchelimsky commented Jun 20, 2012

Unfortunately, respond_to(object, :method).with(:foo) sounds like "respond to object.method by returning foo"

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jun 20, 2012

Member

Yeah, I just realized that. API design is hard :(.

Member

myronmarston commented Jun 20, 2012

Yeah, I just realized that. API design is hard :(.

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jun 20, 2012

Member

More challenging when you have legacy to support :)

Member

dchelimsky commented Jun 20, 2012

More challenging when you have legacy to support :)

@myronmarston myronmarston reopened this Jun 20, 2012

@dnagir

This comment has been minimized.

Show comment
Hide comment
@dnagir

dnagir Jun 21, 2012

Guys, how about this small idea...

Currently I write a lot of things like:

it "calculates thing weekly" do
  Calculator.should_receive(:annual_revenue).with(year: 5).and_return 520
  report.weekly_revenue.should == 10 # 520/52
end

The should_receive syntax is just a bit harder to read and type than what my eye & fingers want to:

it "calculates thing weekly" do
  Calculator.should_receive.annual_revenue(year: 5) { 520 }
  report.weekly_revenue.should == 10 # 520/52
end

Please consider this syntax or similar if it is something you think aligns with RSpec philosophy.

dnagir commented Jun 21, 2012

Guys, how about this small idea...

Currently I write a lot of things like:

it "calculates thing weekly" do
  Calculator.should_receive(:annual_revenue).with(year: 5).and_return 520
  report.weekly_revenue.should == 10 # 520/52
end

The should_receive syntax is just a bit harder to read and type than what my eye & fingers want to:

it "calculates thing weekly" do
  Calculator.should_receive.annual_revenue(year: 5) { 520 }
  report.weekly_revenue.should == 10 # 520/52
end

Please consider this syntax or similar if it is something you think aligns with RSpec philosophy.

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jun 22, 2012

Member

@dnagir that's an interesting idea, but chaining the target method onto should_receive is too different from everything else we do in RSpec IMO. My guess is that what you're looking for is something like RR's syntax, which lets you use the same syntax for the method once you wrap the object: mock(Calculator).annual_revenue(year: 5) { 520 }. That's very nice in terms of mirroring part of the actual use, but I think it's also a bit disconnected due to the mix of wrapping the object. I don't have a better idea at this point, but I'm not in favor of should_receive.annual_revenue (though I am personally in favor of receiving annual revenue).

Member

dchelimsky commented Jun 22, 2012

@dnagir that's an interesting idea, but chaining the target method onto should_receive is too different from everything else we do in RSpec IMO. My guess is that what you're looking for is something like RR's syntax, which lets you use the same syntax for the method once you wrap the object: mock(Calculator).annual_revenue(year: 5) { 520 }. That's very nice in terms of mirroring part of the actual use, but I think it's also a bit disconnected due to the mix of wrapping the object. I don't have a better idea at this point, but I'm not in favor of should_receive.annual_revenue (though I am personally in favor of receiving annual revenue).

@rosenfeld

This comment has been minimized.

Show comment
Hide comment
@rosenfeld

rosenfeld Jun 22, 2012

@dchelimsky how about fake instead of stub?

rosenfeld commented Jun 22, 2012

@dchelimsky how about fake instead of stub?

@rosenfeld

This comment has been minimized.

Show comment
Hide comment
@rosenfeld

rosenfeld Jun 22, 2012

Or pretend?

rosenfeld commented Jun 22, 2012

Or pretend?

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jun 22, 2012

Member

fake already has special meaning: http://xunitpatterns.com/Fake%20Object.html

pretend is interesting, but I don't like it initially - gut feeling. Need to think about it some more.

Member

dchelimsky commented Jun 22, 2012

fake already has special meaning: http://xunitpatterns.com/Fake%20Object.html

pretend is interesting, but I don't like it initially - gut feeling. Need to think about it some more.

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jun 22, 2012

Member

Another possibility: stub_message--it's a bit like my earlier suggestion (stub_method) but retains the vocabulary of sending and receiving messages.

Member

myronmarston commented Jun 22, 2012

Another possibility: stub_message--it's a bit like my earlier suggestion (stub_method) but retains the vocabulary of sending and receiving messages.

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jun 22, 2012

Member

@myronmarston the message is what comes in, the method is how it responds.

Member

dchelimsky commented Jun 22, 2012

@myronmarston the message is what comes in, the method is how it responds.

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jun 22, 2012

Member

on_receipt_of(object, message).with(arguments)?

Actually, I was just thinking about the original allow idea some more. allow would allow us (pardon the pun) to do:

expect(object).to receive(:message)
allow(object).to receive(:message)

I'm still concerned about the potential confusion of the language of "allowing" a real object to receive a message it can already receive anyway, but the symmetry here is really, really nice and I might actually like this one best after all since none of the other ideas have that symmetry and we haven't yet come up with one we're happy with.

Member

myronmarston commented Jun 22, 2012

on_receipt_of(object, message).with(arguments)?

Actually, I was just thinking about the original allow idea some more. allow would allow us (pardon the pun) to do:

expect(object).to receive(:message)
allow(object).to receive(:message)

I'm still concerned about the potential confusion of the language of "allowing" a real object to receive a message it can already receive anyway, but the symmetry here is really, really nice and I might actually like this one best after all since none of the other ideas have that symmetry and we haven't yet come up with one we're happy with.

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jun 22, 2012

Member

@myronmarston agreed so far, but open to other suggestions that maintain the same symmetry without the confusion about what allow means in the context of a real object.

Member

dchelimsky commented Jun 22, 2012

@myronmarston agreed so far, but open to other suggestions that maintain the same symmetry without the confusion about what allow means in the context of a real object.

@mediafinger

This comment has been minimized.

Show comment
Hide comment
@mediafinger

mediafinger Jul 9, 2012

I love the idea to use a consistent syntax for the mocks. And giving the stubs a different name, once the syntax changes, makes sense too. But allow does not sound that natural to me.

Maybe something like adjust or augment could work.

   expect(object).to receive(:message)
   augment(object).to receive(:message)

When staying close to the should_receive syntax, I would prefer something like 'simulate' or 'implements':

   Object.simulate(:method).with(param).and_return xyz
   Object.implements(:method).with(param).and_return xyz

mediafinger commented Jul 9, 2012

I love the idea to use a consistent syntax for the mocks. And giving the stubs a different name, once the syntax changes, makes sense too. But allow does not sound that natural to me.

Maybe something like adjust or augment could work.

   expect(object).to receive(:message)
   augment(object).to receive(:message)

When staying close to the should_receive syntax, I would prefer something like 'simulate' or 'implements':

   Object.simulate(:method).with(param).and_return xyz
   Object.implements(:method).with(param).and_return xyz
@kern

This comment has been minimized.

Show comment
Hide comment
@kern

kern Jul 12, 2012

What about implement rather than allow? It makes sense for real objects.

implement(object, :method) { :bar }

kern commented Jul 12, 2012

What about implement rather than allow? It makes sense for real objects.

implement(object, :method) { :bar }
@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jul 12, 2012

Member

I like the sense given by implement, but it doesn't read well as implement(object).to receive(:message), and I'd really like to have the symmetry of the same basic syntax.

augment (suggested by @mediafinger above) is pretty good, I think. It's certainly better for the case of a real object than allow, although I think for a pure mock object, allow still reads better.

So here's an idea: we can provide all 3 of these:

# sets a mock expectation
expect(object).to receive(:message)

# stubs the method
allow(object).to receive(:message)
augment(object).to receive(:message)

Basically, one of allow and augment would be an alias for the other, allowing the user to use whichever makes the most sense in their context (typically, augment for real objects and allow for pure mock objects).

Member

myronmarston commented Jul 12, 2012

I like the sense given by implement, but it doesn't read well as implement(object).to receive(:message), and I'd really like to have the symmetry of the same basic syntax.

augment (suggested by @mediafinger above) is pretty good, I think. It's certainly better for the case of a real object than allow, although I think for a pure mock object, allow still reads better.

So here's an idea: we can provide all 3 of these:

# sets a mock expectation
expect(object).to receive(:message)

# stubs the method
allow(object).to receive(:message)
augment(object).to receive(:message)

Basically, one of allow and augment would be an alias for the other, allowing the user to use whichever makes the most sense in their context (typically, augment for real objects and allow for pure mock objects).

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jul 12, 2012

Member

We're not augmenting it to receive a message, but to allow it to receive the message. The more I think of this I like allow, and I definitely don't want to add two names for a new feature. FWIW, I thought of "allow" because JMock uses "allowing", so it comes from the mock-library space (just not Ruby).

Member

dchelimsky commented Jul 12, 2012

We're not augmenting it to receive a message, but to allow it to receive the message. The more I think of this I like allow, and I definitely don't want to add two names for a new feature. FWIW, I thought of "allow" because JMock uses "allowing", so it comes from the mock-library space (just not Ruby).

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jul 12, 2012

Member

We're not augmenting it to receive a message, but to allow it to receive the message. The more I think of this I like allow, and I definitely don't want to add two names for a new feature. FWIW, I thought of "allow" because JMock uses "allowing", so it comes from the mock-library space (just not Ruby).

That's certainly true for a pure mock object (which is why I like allow a lot for that case), but IMO allow only makes sense if the object cannot already respond to the message--and with a real object that may not be the case. augment seems like a better word for real objects to me, but even it doesn't really have the right connotation.

Member

myronmarston commented Jul 12, 2012

We're not augmenting it to receive a message, but to allow it to receive the message. The more I think of this I like allow, and I definitely don't want to add two names for a new feature. FWIW, I thought of "allow" because JMock uses "allowing", so it comes from the mock-library space (just not Ruby).

That's certainly true for a pure mock object (which is why I like allow a lot for that case), but IMO allow only makes sense if the object cannot already respond to the message--and with a real object that may not be the case. augment seems like a better word for real objects to me, but even it doesn't really have the right connotation.

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jul 12, 2012

Member

I see what you're saying about real objects, but "augment this object to receive message x" doesn't make any sense based on similar arguments: it can already receive x. I don't have a good answer, but here are some more bad answers to see if any spark better ideas:

tell(object).to respond_to(:message).with(value)
redef(object, :message) { value }
replace(object, :message) { value }

I hate all three :)

Member

dchelimsky commented Jul 12, 2012

I see what you're saying about real objects, but "augment this object to receive message x" doesn't make any sense based on similar arguments: it can already receive x. I don't have a good answer, but here are some more bad answers to see if any spark better ideas:

tell(object).to respond_to(:message).with(value)
redef(object, :message) { value }
replace(object, :message) { value }

I hate all three :)

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jul 12, 2012

Member

I've been thinking recently about the design benefits of pure mock objects. Partial mocks/stubs (i.e. on real objects) don't provide the same design and isolation benefits.

So...I think it makes sense to optimize rspec-mocks for the pure mock case while allowing its use on real objects. allow does this nicely: it reads really, really well for pure mock objects, and a bit funny for real objects. It's a subtle nudge that it's generally better to design your system and tests to work with pure mock objects.

All that is to say: I dislike your 3 suggestions as well, and I'm getting on board with adding expect/allow for mocks/stubs in spite of the funny wording for real objects.

Member

myronmarston commented Jul 12, 2012

I've been thinking recently about the design benefits of pure mock objects. Partial mocks/stubs (i.e. on real objects) don't provide the same design and isolation benefits.

So...I think it makes sense to optimize rspec-mocks for the pure mock case while allowing its use on real objects. allow does this nicely: it reads really, really well for pure mock objects, and a bit funny for real objects. It's a subtle nudge that it's generally better to design your system and tests to work with pure mock objects.

All that is to say: I dislike your 3 suggestions as well, and I'm getting on board with adding expect/allow for mocks/stubs in spite of the funny wording for real objects.

@kern

This comment has been minimized.

Show comment
Hide comment
@kern

kern Jul 13, 2012

+1 for allow. I like that it's borrowed from jMock, so it isn't Ruby-specific vocabulary. I agree with @myronmarston that making partial mocking ugly isn't necessarily bad. It should be discouraged.

kern commented Jul 13, 2012

+1 for allow. I like that it's borrowed from jMock, so it isn't Ruby-specific vocabulary. I agree with @myronmarston that making partial mocking ugly isn't necessarily bad. It should be discouraged.

@rubiii

This comment has been minimized.

Show comment
Hide comment
@rubiii

rubiii Jul 13, 2012

the explanation given by @myronmarston makes sense to me! +1

rubiii commented Jul 13, 2012

the explanation given by @myronmarston makes sense to me! +1

@jwilger

This comment has been minimized.

Show comment
Hide comment
@jwilger

jwilger Jul 20, 2012

I'm also not a big fan of #allow, especially for stubbing methods on real objects (as opposed to pure stub/mock objects). How about #stub_on. I like the way that would read: stub_on( my_object, some_method: 'blah' ).

jwilger commented Jul 20, 2012

I'm also not a big fan of #allow, especially for stubbing methods on real objects (as opposed to pure stub/mock objects). How about #stub_on. I like the way that would read: stub_on( my_object, some_method: 'blah' ).

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jul 21, 2012

Member

I think I could live with stub_on as long as we also use expect_on so the methods align. WDYT?

Member

dchelimsky commented Jul 21, 2012

I think I could live with stub_on as long as we also use expect_on so the methods align. WDYT?

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jul 21, 2012

Member

stub_on and expect_on align nicely. But does it work with the rest of the fluent interface (e.g. with(some, args), exactly(3).times, etc? I'd like to preserve as much of that fluent interface as possible.

Member

myronmarston commented Jul 21, 2012

stub_on and expect_on align nicely. But does it work with the rest of the fluent interface (e.g. with(some, args), exactly(3).times, etc? I'd like to preserve as much of that fluent interface as possible.

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jul 21, 2012

Member

Again w/ the sense. That won't work at all, and I'm at a bit of a loss for new ideas. So far, I think expect/allow is the best pairing. More ideas?

Member

dchelimsky commented Jul 21, 2012

Again w/ the sense. That won't work at all, and I'm at a bit of a loss for new ideas. So far, I think expect/allow is the best pairing. More ideas?

@jwilger

This comment has been minimized.

Show comment
Hide comment
@jwilger

jwilger Jul 21, 2012

Why does that not work at all?

stub_on( my_object, foo: 'bar' )

expect_on( my_object, :foo ).with( 'some', 'args' ).exactly( 3 ).times
# or
expect_on( my_object ).message( :foo ).with( 'some', 'args' ).exactly( 3 ).times

(Not sure #message in the last line would be the best method name, but it illustrates the point.)

jwilger commented Jul 21, 2012

Why does that not work at all?

stub_on( my_object, foo: 'bar' )

expect_on( my_object, :foo ).with( 'some', 'args' ).exactly( 3 ).times
# or
expect_on( my_object ).message( :foo ).with( 'some', 'args' ).exactly( 3 ).times

(Not sure #message in the last line would be the best method name, but it illustrates the point.)

@rosenfeld

This comment has been minimized.

Show comment
Hide comment
@rosenfeld

rosenfeld Jan 13, 2013

I couldn't find any here after looking at several pages: https://github.com/search?q=unstub&p=1&ref=searchbar&type=Code&l=Ruby

rosenfeld commented Jan 13, 2013

I couldn't find any here after looking at several pages: https://github.com/search?q=unstub&p=1&ref=searchbar&type=Code&l=Ruby

@dchelimsky

This comment has been minimized.

Show comment
Hide comment
@dchelimsky

dchelimsky Jan 13, 2013

Member

unstub was added in 384ca8 by @BanTiK and @niessner (iirc at an RSpec hackfest hosted at Obtiva) - can either of you guys remind us of the use case for it?

Member

dchelimsky commented Jan 13, 2013

unstub was added in 384ca8 by @BanTiK and @niessner (iirc at an RSpec hackfest hosted at Obtiva) - can either of you guys remind us of the use case for it?

@mniessner

This comment has been minimized.

Show comment
Hide comment
@mniessner

mniessner Jan 13, 2013

We worked on it in response to (#1). I've never used it, and am not sure if there is a reasonable use case or not.

On Jan 13, 2013, at 2:21 PM, David Chelimsky notifications@github.com wrote:

unstub was added in 384ca8 by @BanTiK and @niessner (iirc at an RSpec hackfest hosted at Obtiva) - can either of you guys remind us of the use case for it?


Reply to this email directly or view it on GitHub.

mniessner commented Jan 13, 2013

We worked on it in response to (#1). I've never used it, and am not sure if there is a reasonable use case or not.

On Jan 13, 2013, at 2:21 PM, David Chelimsky notifications@github.com wrote:

unstub was added in 384ca8 by @BanTiK and @niessner (iirc at an RSpec hackfest hosted at Obtiva) - can either of you guys remind us of the use case for it?


Reply to this email directly or view it on GitHub.

@sethvargo

This comment has been minimized.

Show comment
Hide comment
@sethvargo

sethvargo Jan 13, 2013

Perhaps it can go? Especially since, as @rosenfeld pointed out, no one (on Github) is using it.

sethvargo commented Jan 13, 2013

Perhaps it can go? Especially since, as @rosenfeld pointed out, no one (on Github) is using it.

@tovodeverett

This comment has been minimized.

Show comment
Hide comment
@tovodeverett

tovodeverett Jan 13, 2013

I'm using it. It's useful for a project where you want to globally stub something in spec_helper.rb so that you don't have to remember to stub it all over the place, but then in the actual tests for that code it can be useful to unstub it to verify that the method is working properly. In fact, I'm having to use the alias unstub! because Mocha (which gets included by shoulda-matchers by way of bourne) overwrites unstub, but leaves the alias alone. See #122 for a thread on this that indicates I'm not the only one.

tovodeverett commented Jan 13, 2013

I'm using it. It's useful for a project where you want to globally stub something in spec_helper.rb so that you don't have to remember to stub it all over the place, but then in the actual tests for that code it can be useful to unstub it to verify that the method is working properly. In fact, I'm having to use the alias unstub! because Mocha (which gets included by shoulda-matchers by way of bourne) overwrites unstub, but leaves the alias alone. See #122 for a thread on this that indicates I'm not the only one.

@sethvargo

This comment has been minimized.

Show comment
Hide comment
@sethvargo

sethvargo Jan 13, 2013

@tovodeverett that seems like a very bad idea. You should be using shared examples instead of globally stubbing an object.

sethvargo commented Jan 13, 2013

@tovodeverett that seems like a very bad idea. You should be using shared examples instead of globally stubbing an object.

@tovodeverett

This comment has been minimized.

Show comment
Hide comment
@tovodeverett

tovodeverett Jan 13, 2013

In this case, wouldn't it be shared context, not shared examples?

Actually, I suspect I'd be better off modifying the class in question to add a pair of class methods that effectively stub or unstub the method/behavior in question. Given that I'm stubbing a method on a class I control, it would be very easy to do (in fact, I think I'm going to go do that).

tovodeverett commented Jan 13, 2013

In this case, wouldn't it be shared context, not shared examples?

Actually, I suspect I'd be better off modifying the class in question to add a pair of class methods that effectively stub or unstub the method/behavior in question. Given that I'm stubbing a method on a class I control, it would be very easy to do (in fact, I think I'm going to go do that).

@sethvargo

This comment has been minimized.

Show comment
Hide comment
@sethvargo

sethvargo Jan 13, 2013

Sorry, you're right. That's what I meant. (Cracks open another caffeinated drink).

sethvargo commented Jan 13, 2013

Sorry, you're right. That's what I meant. (Cracks open another caffeinated drink).

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jan 14, 2013

Member

Thanks everyone for keeping this discussion going. I'm glad we have a passionate community of users who can help us figure this stuff out :).

To respond to some specific points:

@myronmarston WRT to stubbing/unstubbing, I propose something like this:
Stubbing
stub(object).my_method # with(param).and_return(:foo)
stub(MyClass).my_class_method

That's a very, very different syntax then anything we've proposed here. It calls a method corresponding to the method you want to stub (as RR does) rather than calling a standardized method, passing the method you want to stub as a symbol argument. It also bifurcates the rspec-mocks syntax into one syntax style for a mocked method and another syntax style for a stubbed method (on top of the older syntax we already have). I don't want to introduce two new syntaxes here.

WRT to the config option, why not leverage the existing :expect and :should?

Because it's an rspec-expectations config option, not a general rspec option. On top of that, many projects have already switched to the new rspec-expectations syntax (bundler and many of @sferik's projects come to mind) but they obviously haven't started using a new mock syntax since we haven't created it yet...which means that they need to be able to upgrade and change their config to the new syntax in their own time. We can't use the existing option to mean a change to the syntax here as well, or we'll cause lots of breakage during upgrades.

Anyhow, I still think that allow is the best proposal for a stubbing syntax. It mirrors expect exactly:

expect(obj).to receive(:foo).with(arg)
allow(obj).to receive(:foo).with(arg)

I like the idea of making trimming down the number of ways to create a test double to just double (i.e. deprecating stub and mock for this purpose) but I'm not on board with changing the meaning/semantics of stub to something entirely new as part of this syntax change. Having a method that has entirely different semantics depending on a config option is a recipe for disaster. It creates confusion for folks contributing to a project that uses rspec (e.g. "what does stub mean here? I have to go look at all the files where rspec may be configured to figure it out), and imagine the confusion for newcomers to rspec. Or just think about the complexity of the API docs for stub: "does X when config option Y is set to Z; or when config option Y is set to W, does this entirely different thing". I can just imagine the tickets we're going to get if we make that change...

So, I'm planning to go with expect and allow. Deprecating stub and mock as alternates for double can be a separate change. If someone really wants to use stub over allow then they're welcome to alias it since ruby makes that so easy :).

Finally, given that unstub is used so rarely, and what sounds like the main use case (being able to almost globally stub something) has a better solution now that we have shared contexts, my inclination is to not worry about bringing it forward to the new syntax.

Member

myronmarston commented Jan 14, 2013

Thanks everyone for keeping this discussion going. I'm glad we have a passionate community of users who can help us figure this stuff out :).

To respond to some specific points:

@myronmarston WRT to stubbing/unstubbing, I propose something like this:
Stubbing
stub(object).my_method # with(param).and_return(:foo)
stub(MyClass).my_class_method

That's a very, very different syntax then anything we've proposed here. It calls a method corresponding to the method you want to stub (as RR does) rather than calling a standardized method, passing the method you want to stub as a symbol argument. It also bifurcates the rspec-mocks syntax into one syntax style for a mocked method and another syntax style for a stubbed method (on top of the older syntax we already have). I don't want to introduce two new syntaxes here.

WRT to the config option, why not leverage the existing :expect and :should?

Because it's an rspec-expectations config option, not a general rspec option. On top of that, many projects have already switched to the new rspec-expectations syntax (bundler and many of @sferik's projects come to mind) but they obviously haven't started using a new mock syntax since we haven't created it yet...which means that they need to be able to upgrade and change their config to the new syntax in their own time. We can't use the existing option to mean a change to the syntax here as well, or we'll cause lots of breakage during upgrades.

Anyhow, I still think that allow is the best proposal for a stubbing syntax. It mirrors expect exactly:

expect(obj).to receive(:foo).with(arg)
allow(obj).to receive(:foo).with(arg)

I like the idea of making trimming down the number of ways to create a test double to just double (i.e. deprecating stub and mock for this purpose) but I'm not on board with changing the meaning/semantics of stub to something entirely new as part of this syntax change. Having a method that has entirely different semantics depending on a config option is a recipe for disaster. It creates confusion for folks contributing to a project that uses rspec (e.g. "what does stub mean here? I have to go look at all the files where rspec may be configured to figure it out), and imagine the confusion for newcomers to rspec. Or just think about the complexity of the API docs for stub: "does X when config option Y is set to Z; or when config option Y is set to W, does this entirely different thing". I can just imagine the tickets we're going to get if we make that change...

So, I'm planning to go with expect and allow. Deprecating stub and mock as alternates for double can be a separate change. If someone really wants to use stub over allow then they're welcome to alias it since ruby makes that so easy :).

Finally, given that unstub is used so rarely, and what sounds like the main use case (being able to almost globally stub something) has a better solution now that we have shared contexts, my inclination is to not worry about bringing it forward to the new syntax.

@jwilger

This comment has been minimized.

Show comment
Hide comment
@jwilger

jwilger Jan 14, 2013

On 01/13, Myron Marston wrote:

I like the idea of making trimming down the number of ways to create a
test double to just double (i.e. deprecating stub and mock for
this purpose) but I'm not on board with changing the meaning/semantics
of stub to something entirely new as part of this syntax change.
Having a method that has entirely different semantics depending on a
config option is a recipe for disaster. It creates confusion for
folks contributing to a project that uses rspec (e.g. "what does
stub mean here? I have to go look at all the files where rspec may
be configured to figure it out), and imagine the confusion for
newcomers to rspec. Or just think about the complexity of the API
docs for stub: "does X when config option Y is set to Z; or when
config option Y is set to W, does this entirely different thing". I
can just imagine the tickets we're going to get if we make that
change...

So, I'm planning to go with expect and allow. Deprecating stub
and mock as alternates for double can be a separate change. If
someone really wants to use stub over allow then they're welcome
to alias it since ruby makes that so easy :).

Finally, given that unstub is used so rarely, and what sounds like
the main use case (being able to almost globally stub something) has a
better solution now that we have shared contexts, my inclination is to
not worry about bringing it forward to the new syntax.

FWIW, this plan gets a +1 from me.

jwilger commented Jan 14, 2013

On 01/13, Myron Marston wrote:

I like the idea of making trimming down the number of ways to create a
test double to just double (i.e. deprecating stub and mock for
this purpose) but I'm not on board with changing the meaning/semantics
of stub to something entirely new as part of this syntax change.
Having a method that has entirely different semantics depending on a
config option is a recipe for disaster. It creates confusion for
folks contributing to a project that uses rspec (e.g. "what does
stub mean here? I have to go look at all the files where rspec may
be configured to figure it out), and imagine the confusion for
newcomers to rspec. Or just think about the complexity of the API
docs for stub: "does X when config option Y is set to Z; or when
config option Y is set to W, does this entirely different thing". I
can just imagine the tickets we're going to get if we make that
change...

So, I'm planning to go with expect and allow. Deprecating stub
and mock as alternates for double can be a separate change. If
someone really wants to use stub over allow then they're welcome
to alias it since ruby makes that so easy :).

Finally, given that unstub is used so rarely, and what sounds like
the main use case (being able to almost globally stub something) has a
better solution now that we have shared contexts, my inclination is to
not worry about bringing it forward to the new syntax.

FWIW, this plan gets a +1 from me.

@jfelchner

This comment has been minimized.

Show comment
Hide comment
@jfelchner

jfelchner Jan 30, 2013

I got to this discussion way too late, but I'm really glad the decision everyone came to. The consistency of the expect syntax and the new allow syntax reads great.

Because it was brought up earlier in the discussion and because looking for spies is what led me here, I just wanted to make sure we come back to that point, and finalize a syntax for, test spies as well. For the purposes of keeping the discussion moving forward, I'm going to summarize here. Both of these syntaxes I like very much.

Current

Our current syntax (without spies) would produce something like this:

# http://www.imdb.com/title/tt0102926/
context 'when Buffalo Bill gives his captive the hose' do
  it 'puts the lotion in the basket' do
    expect(basket).to receive(:<<).with(lotion).once

    BuffaloBill.spray_water_on_captive
  end
end

Option 1

Earlier in this PR it was proposed to do something like this:

context 'when Buffalo Bill gives his captive the hose' do
  it 'puts the lotion in the basket' do
    expect { BuffaloBill.spray_water_on_captive }.to send(:<<).to(basket).with(lotion).once
  end
end

And it appeared that the only stumbling block was around whether to override send in the context of the matcher. Readability-wise, I think this is great, although it is quite a bit to chew off one one line.

Option 2

Another option that was proposed was have_received which also has its advantages.

context 'when Buffalo Bill gives his captive the hose' do
  it 'puts the lotion in the basket' do
    allow(basket).to receive(:<<)

    BuffaloBill.spray_water_on_captive

    expect(basket).to have_received(:<<).with(lotion).once
  end
end

Also a nice option.

My Opinion

Honestly I kind of like the second option slightly more because building up the stub may need to be done in a separate context which would make option 1 basically unusable.

Thoughts everyone?

jfelchner commented Jan 30, 2013

I got to this discussion way too late, but I'm really glad the decision everyone came to. The consistency of the expect syntax and the new allow syntax reads great.

Because it was brought up earlier in the discussion and because looking for spies is what led me here, I just wanted to make sure we come back to that point, and finalize a syntax for, test spies as well. For the purposes of keeping the discussion moving forward, I'm going to summarize here. Both of these syntaxes I like very much.

Current

Our current syntax (without spies) would produce something like this:

# http://www.imdb.com/title/tt0102926/
context 'when Buffalo Bill gives his captive the hose' do
  it 'puts the lotion in the basket' do
    expect(basket).to receive(:<<).with(lotion).once

    BuffaloBill.spray_water_on_captive
  end
end

Option 1

Earlier in this PR it was proposed to do something like this:

context 'when Buffalo Bill gives his captive the hose' do
  it 'puts the lotion in the basket' do
    expect { BuffaloBill.spray_water_on_captive }.to send(:<<).to(basket).with(lotion).once
  end
end

And it appeared that the only stumbling block was around whether to override send in the context of the matcher. Readability-wise, I think this is great, although it is quite a bit to chew off one one line.

Option 2

Another option that was proposed was have_received which also has its advantages.

context 'when Buffalo Bill gives his captive the hose' do
  it 'puts the lotion in the basket' do
    allow(basket).to receive(:<<)

    BuffaloBill.spray_water_on_captive

    expect(basket).to have_received(:<<).with(lotion).once
  end
end

Also a nice option.

My Opinion

Honestly I kind of like the second option slightly more because building up the stub may need to be done in a separate context which would make option 1 basically unusable.

Thoughts everyone?

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Jan 30, 2013

Member

@jfelchner -- I'm glad to discuss spies as a possible feature for inclusion in a future rspec-mocks version, but I think it's a separate issue from this one (though it may build on top of the syntax discussed here). Can you open a separate ticket so we can discuss it there? I think your comment is likely to get "lost" on this issue, given how far down it is in the discussion. Thanks!

Member

myronmarston commented Jan 30, 2013

@jfelchner -- I'm glad to discuss spies as a possible feature for inclusion in a future rspec-mocks version, but I think it's a separate issue from this one (though it may build on top of the syntax discussed here). Can you open a separate ticket so we can discuss it there? I think your comment is likely to get "lost" on this issue, given how far down it is in the discussion. Thanks!

@JonRowe

This comment has been minimized.

Show comment
Hide comment
@JonRowe

JonRowe Mar 3, 2013

Member

What was the outcome of this? Is it still awaiting future development?

Member

JonRowe commented Mar 3, 2013

What was the outcome of this? Is it still awaiting future development?

@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Mar 4, 2013

Member

What was the outcome of this? Is it still awaiting future development?

I'm still planning on working on it; other, more immediate issues have been taking my time recently. But this is next on my list of "new features" to work on.

Member

myronmarston commented Mar 4, 2013

What was the outcome of this? Is it still awaiting future development?

I'm still planning on working on it; other, more immediate issues have been taking my time recently. But this is next on my list of "new features" to work on.

@JonRowe

This comment has been minimized.

Show comment
Hide comment
@JonRowe

JonRowe Mar 4, 2013

Member

👍

Member

JonRowe commented Mar 4, 2013

👍

myronmarston added a commit that referenced this issue Mar 18, 2013

Move `stub_chain` functionality out of `RSpec::Mocks::Methods`
...while maintaining the same API.

This allows us to remove the `format_chain` method from every object and
begins to prepare us for the future addition of a new expect-based syntax
to rspec-mocks (#153).

myronmarston added a commit that referenced this issue Mar 25, 2013

Externalize methods and state that was previously held on all objects.
- Remove `@mock_proxy` ivar
- Remove `rspec_verify`, `rspec_reset`, `__mock_proxy` and `__remove_mock_proxy` methods.

This is a refactoring that I'm doing to pave the way for the new expect
syntax (#153). As that syntax "wraps" objects in order to mock or stub
them, we need to externalize these methods and state. The methods directly
on the object (e.g. `stub` and `should_receive`) will simply delegate to
this external logic.

This refactoring had some nice side benefits:

- No need for the hacky YAML fix. It was only needed because we were storing
  `@mock_proxy` on the mocked object.
- AnyInstance no longer needs to much with `dup`; again, this was only needed
  because it dup'd the `@mock_proxy` ivar.
- The Marshal extension gets significantly simpler (again, due to not
  storing `@mock_proxy` on the object anymore).

Rather than storing the mock proxies on the objects, we are now storing
them in a hash, keyed by object_id.  This is pretty simple and consistent,
but could be problematic for objects that muck with `object_id`. That method
seems a bit sacred, though, so I'm not too worried about it.
@myronmarston

This comment has been minimized.

Show comment
Hide comment
@myronmarston

myronmarston Apr 4, 2013

Member

I've started working on this feature in the new_syntax branch, for anyone who cares to try it out or follow along. A few things to note:

  • We never discussed any_instance on this ticket before. For now, I'm going with expect_any_instance_of(MyClass).to receive and allow_any_instance_of(MyClass).to receive. @alindeman also put up a gist with some syntax ideas (which try to address the occasionally confusing use of any). Feedback welcome.
  • There are a couple features available on the current syntax that I can't think of a good syntax for and will probably not make the initial cut (unless someone can come up with good syntaxes). These are features I personally don't use much so I'm OK with it but I'm curious what others think:
    • stub_chain -- This is usually a code smell, anyway.
    • my_double.stub(:msg_1 => "value", :msg_2 => "value") as a shorthand for my_double.stub(:msg_1).and_return("value"); my_double.stub(:msg_2).and_return("value"). IMO the main time the hash syntax is useful is when creating a test double, and you can still pass a hash to double and it will be treated in this fashion.
  • I'm planning to include this in RSpec 2.14. (Along with the test spies feature @jferris added recently).

Thanks to everyone for your patience on this.

Member

myronmarston commented Apr 4, 2013

I've started working on this feature in the new_syntax branch, for anyone who cares to try it out or follow along. A few things to note:

  • We never discussed any_instance on this ticket before. For now, I'm going with expect_any_instance_of(MyClass).to receive and allow_any_instance_of(MyClass).to receive. @alindeman also put up a gist with some syntax ideas (which try to address the occasionally confusing use of any). Feedback welcome.
  • There are a couple features available on the current syntax that I can't think of a good syntax for and will probably not make the initial cut (unless someone can come up with good syntaxes). These are features I personally don't use much so I'm OK with it but I'm curious what others think:
    • stub_chain -- This is usually a code smell, anyway.
    • my_double.stub(:msg_1 => "value", :msg_2 => "value") as a shorthand for my_double.stub(:msg_1).and_return("value"); my_double.stub(:msg_2).and_return("value"). IMO the main time the hash syntax is useful is when creating a test double, and you can still pass a hash to double and it will be treated in this fashion.
  • I'm planning to include this in RSpec 2.14. (Along with the test spies feature @jferris added recently).

Thanks to everyone for your patience on this.

@myronmarston myronmarston referenced this issue Apr 5, 2013

Merged

New syntax #266

@samphippen

This comment has been minimized.

Show comment
Hide comment
@samphippen

samphippen May 11, 2013

Member

@myronmarston can this be closed now #266 is merged?

Member

samphippen commented May 11, 2013

@myronmarston can this be closed now #266 is merged?

@leifg

This comment has been minimized.

Show comment
Hide comment
@leifg

leifg Dec 3, 2013

Just a general question:

does a pendant for unstub exist in the new expect syntax?

And if not, wouldn't it be good to have an according notice in the deprecation message.

All I currently (3.0 beta1) get is:

sing `unstub` from rspec-mocks' old `:should` syntax without explicitly enabling the syntax is deprecated. Use the new `:expect` syntax or explicitly enable `:should` instead. Called from some_spec.rb:23:in `block (2 levels) in <top (required)>'.

leifg commented Dec 3, 2013

Just a general question:

does a pendant for unstub exist in the new expect syntax?

And if not, wouldn't it be good to have an according notice in the deprecation message.

All I currently (3.0 beta1) get is:

sing `unstub` from rspec-mocks' old `:should` syntax without explicitly enabling the syntax is deprecated. Use the new `:expect` syntax or explicitly enable `:should` instead. Called from some_spec.rb:23:in `block (2 levels) in <top (required)>'.
@JonRowe

This comment has been minimized.

Show comment
Hide comment
@JonRowe

JonRowe Dec 3, 2013

Member

I don't believe we have a replacement for unstub we should probably add a note that it's only available using :should.

As an aside I've always seen it as a test smell, so I don't think it's worth bring across.

Member

JonRowe commented Dec 3, 2013

I don't believe we have a replacement for unstub we should probably add a note that it's only available using :should.

As an aside I've always seen it as a test smell, so I don't think it's worth bring across.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment