Question: 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](https://www.relishapp.com/rspec/rspec-mocks/docs/method-stubs/stub-on-any-instance-of-a-class) 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?

Answer: 
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.
There are many ways to write to stderr, so it's usually better to test the resulting string instead of requiring `puts` was called once with specific arguments.

As long as your function uses `$stderr` (which is intended to changable) rather than `STDERR` const, you can use rspec's beautiful [`output` matcher](https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/output-matcher):

```
expect { blather("zoo") }.to output(/=== zoo/).to_stderr

```

If you need more control, you could replace `$stderr` (and maybe `stub_const "STDERR"`) with a `StringIO` instance, and make assertions about its `.string` later...
(This is what output matcher [does internally](https://github.com/rspec/rspec-expectations/blob/v3.6.0/lib/rspec/matchers/built_in/output.rb#L157-L168).)