我有一个简单的功能,我想测试(也许主要是为了安抚simplecov)。功能是:
module Utils
extend self
def blather(msg)
msg = "=== " + msg
STDERR.puts(msg)
Rails.logger.debug(msg)
end
end
RSpec documentation for stubbing说:
消息可以存储在任何类上,包括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类)?这是失败的,因为它是一种类方法吗?或者这种测试是否有更明智的策略?
答案 0 :(得分: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
是一个普通的对象,所以你可以像平常那样存在方法,并设置它的期望值。
答案 1 :(得分:2)
有很多方法可以写入stderr,因此测试结果字符串通常更好,而不是要求puts
使用特定参数调用一次。
只要您的函数使用$stderr
(旨在改变)而不是STDERR
const,您就可以使用rspec的漂亮output
matcher:
expect { blather("zoo") }.to output(/=== zoo/).to_stderr
如果您需要更多控制权,可以使用$stderr
实例替换stub_const "STDERR"
(可能还有StringIO
),然后再对其.string
进行断言...
(这是输出匹配器does internally。)
答案 2 :(得分:1)
咄。 STDIO不是一个类 - 它是IO的一个实例,所以改变:
STDERR.any_instance.should_receive(:puts).with("=== zoo")
到
STDERR.should_receive(:puts).with("=== zoo")
让测试通过。