Can I stub STDERR in RSpec?

rspec, ruby, stub

Solution

Firstly, you should typically use `$stderr` rather than `STDERR`.

module Utils
  extend self

  def blather(msg)
    msg = "=== " + msg
    $stderr.puts(msg)
    Rails.logger.debug(msg)
  end

end

To answer your question, you can do the following in RSpec:

describe Utils do
  context "blather" do
    it "should print to stderr" do
      $stderr.should_receive(:puts).with("=== zoo")
      Utils.blather("zoo")
    end
  end
end

You just stub the method via `$stderr.should_receive`. Because `$stderr` is a normal object, you can stub methods on it like normal as well as set up expectations on it.

Problem

I have a simple function that I'd like to test (perhaps mostly to appease simplecov). The function is: ``` module Utils extend self def blather(msg) msg = "=== " + msg STDERR.puts(msg) Rails.logger.debug(msg) end end ``` The RSpec documentation for stubbing says that: Messages can be stubbed on any class, including those in Ruby's core library. But the following: ``` # file: spec/lib/utils_spec.rb require 'spec_helper' describe Utils do context "blather" do it "should print to STDERR" do STDERR.any_instance.should_receive(:puts).with("=== zoo") Utils.blather("zoo") end end end ``` ... I get an error ``` undefined method `any_instance' for #<IO:<STDERR>> ``` Putting aside questions as to whether this test makes any sense, is it possible to stub STDERR (the IO class)? Is this failing because it's a class method? Or is there a more sensible strategy for this kind of test?

Original source

Related problems