1

Is it possible to stub an entire chain using Mocha? For example, I want to stub:

User.first.posts.find(params[:id])

such that it returns a predefined post instance instead of accessing the database. Ideally, I'd want to do something like:

@post = Post.new
User.any_instance.stubs(:posts,:find).returns(@post)

As you can see, I'm stubbing out both the 'posts' and 'find' methods together. Obviously this isn't working right now, but is there a way I can achieve this effect? Thanks.

EDIT: I found the following online which hacks a way to do this:

module Mocha
  module ObjectMethods
    def stub_path(path)
      path = path.split('.') if path.is_a? String
      raise "Invalid Argument" if path.empty?
      part = path.shift
      mock = Mocha::Mockery.instance.named_mock(part)
      exp = self.stubs(part)
      if path.length > 0
        exp.returns(mock)
        return mock.stub_path(path)
      else
        return exp
      end
    end
  end
end

With this, you can call User.any_instance.stub_path('posts.find').returns(@post)

pushmatrix
  • 726
  • 1
  • 9
  • 23

1 Answers1

1

Based on http://viget.com/extend/stubbing-method-chains-with-mocha you can try:

User.stubs(:first).returns(stub(:posts => stub(:find => @post)))

Although I could only get this form to work:

find = stub
find.stubs(:find).returns(@post)
posts = stub
posts.stubs(:find).returns(find)
User.stubs(:first).returns(posts)
Steve
  • 1,084
  • 11
  • 17
  • 2
    This is a very late reply, but in case it's useful to anyone... The post you linked to is a good one, but the syntax is old. Calling [stub requires a name as the first argument](http://gofreerange.com/mocha/docs/Mocha/API.html#stub-instance_method). So stubbing, for example, `Rails.env.production?` to return `true` would be `Rails.stubs(:env).returns(stub('production?', production?: true))` – Mike T Aug 16 '17 at 19:55
  • 1
    The documentation is missing something: `User.stubs(:first).returns(stub.stubs(:posts => stub.stubs(:find => @post)))` You have to use `stub.stubs` to create the instance and then use its method. – Okomikeruko Jul 18 '23 at 14:29