25

Though my question is pretty straightforward, I failed to find an answer around here:

How can I stub a method and return the parameter itself (for example on a method that does an array-operation)?

Something like this:

 interface.stub!(:get_trace).with(<whatever_here>).and_return(<whatever_here>)
Len
  • 2,093
  • 4
  • 34
  • 51

3 Answers3

30

Note: The stub method has been deprecated. Please see this answer for the modern way to do this.


stub! can accept a block. The block receives the parameters; the return value of the block is the return value of the stub:

class Interface
end

describe Interface do
  it "should have a stub that returns its argument" do
    interface = Interface.new
    interface.stub!(:get_trace) do |arg|
      arg
    end
    interface.get_trace(123).should eql 123
  end
end
Community
  • 1
  • 1
Wayne Conrad
  • 103,207
  • 26
  • 155
  • 191
  • Thanks, this is exactly what I was looking for! I knew the answer had to be something simple :) – Len May 09 '11 at 15:55
  • @SirLenzOrlot, You're welcome! Thanks for the checkmark, and happy hacking. – Wayne Conrad May 09 '11 at 16:15
  • Can this be combined with a situation where sequence plays a role (for example the first time it is called it returns the parameter, the next time it returns "disconnected")? – Len Oct 13 '11 at 12:35
  • @Sir, Yes, but it doesn't seem like the easy way to do things. Why not just spec that it should receive (for example) "foo" and return "foo", and then receive "bar" and return "disconnected?" – Wayne Conrad Oct 14 '11 at 22:22
  • I've got two answers at http://stackoverflow.com/questions/7754733/rspec-stubbing-return-in-a-sequence/7756109 – Len Oct 17 '11 at 14:49
  • @Sir, good question and good answers. Jacob S's answer there is what I had in mind. – Wayne Conrad Oct 17 '11 at 19:28
21

The stub method has been deprecated in favor of expect.

expect(object).to receive(:get_trace).with(anything) do |value| 
  value
end

https://relishapp.com/rspec/rspec-mocks/v/3-2/docs/configuring-responses/block-implementation

Kiyose
  • 311
  • 2
  • 3
8

You can use allow (stub) instead of expect (mock):

allow(object).to receive(:my_method_name) { |param1, param2| param1 }

With named parameters:

allow(object).to receive(:my_method_name) { |params| params[:my_named_param] }

Here is a real life example:

Let's assume we have a S3StorageService that uploads our files to S3 using the upload_file method. That method returns the S3 direct URL to our uploaded file.

def self.upload_file(file_type:, pathname:, metadata: {}) …

We want to stub that upload for many reasons (offline testing, performance improvements…):

allow(S3StorageService).to receive(:upload_file) { |params| params[:pathname] }

That stub only returns the file path.

Maxime Brehin
  • 377
  • 6
  • 4