Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSpec any_instance return self

Tags:

ruby

rspec

I'm trying to stub any instance of some class. I need to stub the fetch method, which fills the self with some data.

How can I get access to self variable, modify it and return on fetch method?

MyObject.any_instance.stub(:fetch) { self }

doesn't return a MyObject instance.

Maybe, mocks is more useful in this situation. Unfortunately, I haven't understood they yet.

like image 354
Kukunin Avatar asked Dec 15 '12 15:12

Kukunin


People also ask

What is Allow_any_instance_of?

Use allow_any_instance_of(Class).to receive when you want to configure how. instances of the given class respond to a message without setting an. expectation that the message will be received.

How do I mock a method in RSpec?

Mocking with RSpec is done with the rspec-mocks gem. If you have rspec as a dependency in your Gemfile , you already have rspec-mocks available.

What is stubbing in RSpec?

In RSpec, a stub is often called a Method Stub, it's a special type of method that “stands in” for an existing method, or for a method that doesn't even exist yet.

What is double in RSpec?

RSpec features doubles that can be used as 'stand-ins' to mock an object that's being used by another object. Doubles are useful when testing the behaviour and interaction between objects when we don't want to call the real objects - something that can take time and often has dependencies we're not concerned with.


1 Answers

There's an open rspec-mocks issue to address this. I hope to get around to addressing it at some point, but it's not simple to add this in a way that doesn't break existing spec suites that use any_instance with a block implementation, because we would start yielding an additional argument (e.g. the object instance).

Overall, any_instance can come in handy in some situations, but it's a bit of a smell, and you'll generally have fewer issues if you can find a way to mock or stub individual instances.

Here's a work around that I have not tested but should work:

orig_new = MyObject.method(:new)
MyObject.stub(:new) do |*args, &block|
  orig_new.call(*args, &block).tap do |instance|
    instance.stub(:fetch) { instance }
  end
end

Essentially, we're simulating any_instance here by hooking into MyObject.new so that we can stub fetch on each new instance that is instantiated.

All that said, it's important to "listen to your tests", and, when something is hard to test, consider what that says about your design, rather than immediately using power tools like any_instance. Your original question doesn't give enough context for me to speculate anything about your design, but it's definitely where I would start when faced with a need to do this.

like image 105
Myron Marston Avatar answered Sep 20 '22 12:09

Myron Marston