3

我有一个我想测试的简单功能(也许主要是为了安抚 simplecov)。功能是:

module Utils
  extend self

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

end

存根的RSpec 文档说:

消息可以在任何类上存根,包括 Ruby 核心库中的那些。

但以下内容:

# 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

...我收到一个错误

undefined method `any_instance' for #<IO:<STDERR>>

抛开这个测试是否有意义的问题,是否可以存根 STDERR(IO 类)?这是因为它是类方法而失败吗?或者这种测试有更明智的策略吗?

4

3 回答 3

6

首先,您通常应该使用$stderr而不是STDERR.

module Utils
  extend self

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

end

要回答您的问题,您可以在 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

您只需通过$stderr.should_receive. 因为$stderr它是一个普通对象,所以您可以像普通对象一样在其上存根方法,并对其设置期望值。

于 2012-04-11T15:26:16.607 回答
3

有很多方法可以写入 stderr,因此最好测试生成的字符串,而不是要求puts使用特定参数调用一次。

只要您的函数使用$stderr(旨在更改)而不是STDERRconst,您就可以使用 rspec 的漂亮output匹配器

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

如果您需要更多控制,您可以用一个实例替换$stderr(并且可能) ,然后对其进行断言......(这是输出匹配器在内部所做的。)stub_const "STDERR"StringIO.string

于 2017-09-27T09:59:58.843 回答
1

呃。STDIO 不是一个类——它是 IO 的一个实例,所以改变:

STDERR.any_instance.should_receive(:puts).with("=== zoo")

STDERR.should_receive(:puts).with("=== zoo")

使测试通过。

于 2012-04-11T16:08:46.867 回答