2012-04-11 111 views
3

我有一個簡單的函數,我想測試(也許主要是爲了安撫simplecov)。該功能是:我可以在RSpec中存儲STDERR嗎?

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類)?這是失敗的,因爲它是一個類方法?或者是否有這種測試更明智的策略?

回答

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是一個普通的對象,所以你可以像對普通對象一樣存根方法,並設置對它的期望值。

+0

是的 - 見下面我的「咄」的答案。 – 2012-04-11 17:28:28

+0

PS:感謝有關傾向於STDERR的$ stderr的提示 - (http://stackoverflow.com/questions/4279604/what-is-the-difference-between-stdin-and-stdin-in-ruby解釋說$ stderr可以被重新分配,而STDERR不能)。 – 2012-04-11 17:29:54

1

Duh。 STDIO不是類 - 它是IO的一個實例,因此改變:

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

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

使試驗合格。

1

有很多方法可以寫入stderr,所以通常測試結果字符串會更好,而不需要使用puts來調用一次特定的參數。

只要你的函數使用$stderr(其目的是多變的),而不是STDERR常量,您可以使用rspec的美麗output matcher

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

如果您需要更多的控制,你可以取代$stderr(也許stub_const "STDERR")與StringIO實例,並作出斷言關於其.string後... (這是輸出匹配does internally

相關問題