Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stubbing Chained Methods with Rspec

I want to call a named_scope that will only return one record, but the named_scope returns an array, that's not a big deal as I can just chain it with .first:

Model.named_scope(param).first

and this works, what I am struggling with is how to stub the chained call. Does anyone have a reference or an answer on how I would go about achieving this with Rspec mocking?

like image 238
nitecoder Avatar asked Mar 20 '09 02:03

nitecoder


People also ask

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 stub and mock in RSpec?

A Test Stub is a fake thing you stick in there to trick your program into working properly under test. A Mock Object is a fake thing you stick in there to spy on your program in the cases where you're not able to test something directly.

What is allow in RSpec?

Use the allow method with the receive matcher on a test double or a real. object to tell the object to return a value (or values) in response to a given. message. Nothing happens if the message is never received.


2 Answers

I figured something out.

Client.stub!(:named_scope).and_return(@clients = mock([Client]))
@clients.stub!(:first).and_return(@client = mock(Client))

which allows me to call my controller:

@client = Client.named_scope(param).first

It works, but is there a better solution?

EDIT:

The release of rspec 1.2.6 allows us to use stub_chain meaning it can now be:

Client.stub_chain(:named_scope, :chained_call).and_return(@clients = [mock(Client)])

This was top of my head, as always check the api for specifics :)

like image 93
nitecoder Avatar answered Nov 04 '22 22:11

nitecoder


Better version of

Client.stub!(:named_scope).and_return(@clients = mock([Client]))
@clients.stub!(:first).and_return(@client = mock(Client))

will be:

Client.should_receive(:named_scope).with(param).and_return do
  record = mock_model(Comm)
  record.should_receive(:do_something_else)
  [record]  
end
like image 2
luacassus Avatar answered Nov 05 '22 00:11

luacassus