Skip to content
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

How to simply stub objects #39

Closed
ryancheung opened this issue Jul 19, 2013 · 11 comments
Closed

How to simply stub objects #39

ryancheung opened this issue Jul 19, 2013 · 11 comments

Comments

@ryancheung
Copy link

Every time i want to stub an object. I have to do like this:

order =  Object.new
stub(order).item_total { 200 }

Is there any simple way stub a object like what rspec mock does:

  let(:order) { mock('order', item_total: 200) }
@mcmire
Copy link
Contributor

mcmire commented Jul 19, 2013

Yes, #stub! will do what you want. So you can say

stub!.item_total { 200 }

Note that you are not able to access the stubbed object in this case, but
if you want that then either say

order = stub! do
  item_total { 200 }
end

or if you expect to only ever have one method you are stubbing then you can
use #subject to get at the object:

order = stub!.item_total { 200 }.subject

HTH.

@ryancheung
Copy link
Author

Thank you very much! And I suggest that this usage should be put into the README.

@mcmire
Copy link
Contributor

mcmire commented Jul 20, 2013

Yeah it's actually in the API overview: https://github.com/rr/rr/blob/master/doc/03_api_overview.md#double-graphs. I need to clean this section up, though.

@ryancheung ryancheung reopened this Jul 22, 2013
@ryancheung
Copy link
Author

@mcmire I still have problems here. stub! do item_total { 200 } end would return a instance of RR::DoubleDefinitions::DoubleDefinition, but it should return a instance of Object. While stub!.item_total { 200 }.subject works. It returns a Object with its item_total method stubbed.

@mcmire
Copy link
Contributor

mcmire commented Jul 22, 2013

Ah. Actually that makes sense now. You're right, #stub! does return a DoubleDefinition regardless of whether or not you give it a block. So, you want this instead:

order = stub! do
  item_total { 200 }
end.subject

...Only, this doesn't actually work, because I think there's a bug in RR that double-wraps a DoubleDefinition when using the block form. You have to say this instead:

order = stub! do
  item_total { 200 }
end.subject.subject

For this reason I would recommend sticking with the inline form:

order = stub!.item_total { 200 }.subject

If you need to add more methods you can do that easily:

order = stub!.
  item_total { 200 }.
  another_method { :whatever }.
  subject

@ryancheung
Copy link
Author

It's not perfect enough, but it works. Thanks for the help!

@mcmire
Copy link
Contributor

mcmire commented Jul 23, 2013

Cool glad I could help. I might consider another way to make this more elegant in the future, Mocha and rspec-mocks definitely have RR beat here.

@ryancheung
Copy link
Author

@mcmire Yep, they do. But unfortunately, the inline form you recommended not work again now. I got these:

  1) OrderCouponValidator#validate with order that has a coupon_code and the coupon code exists add errors to order if the coupon code 
is not usable
     Failure/Error: changes { {} }.
     NoMethodError:
       undefined method `changes' for #<RR::DoubleDefinitions::DoubleDefinition:0x007f9b0f28bb38>
     # ./spec/models/order_coupon_validator_spec.rb:8:in `block (3 levels) in <top (required)>'
     # ./spec/models/order_coupon_validator_spec.rb:20:in `block (4 levels) in <top (required)>'

The mocking code is:

    let(:order) do
      stub!.
        errors { ActiveModel::Errors.new(Object.new) }.
        changes { {} }.
        subject
    end

I'm using Rails 3.2.13 btw.

Just point out that problem.

@mcmire
Copy link
Contributor

mcmire commented Jul 23, 2013

OMG I am so dumb. Of course that doesn't work.

Okay let's try this again:

let(:order) do
  Object.new.tap do |obj|
    stub(obj).item_total { 200 }
    stub(obj).another_method { :whatever }
  end
end

It isn't the most elegant thing in the world but I think that should actually work.

@contentfree
Copy link

Commenting on an old, old closed issue, but…

So is the documentation wrong? When I try to use RR as suggested in the docs, eg. mock!.my_method { "something" } I, too, get the undefined method error that @ryancheung got. Can the docs be updated (I know I know, PRs welcome… but what's the "right" way?)

@kou
Copy link
Member

kou commented Feb 18, 2018

First, can you open a new issue with a script that shows the problem and is runnable?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants