使用rspec测试`until`

时间:2013-12-08 08:07:28

标签: ruby rspec

我试图测试一个用户输入影响直到循环,但我很难理解如何把它拉下来...我需要一些灵感。你会怎么做?

class Menu
  @@menu = nil

  def get_menu
    menu = nil
    until menu == 'foo'
      menu = Readline.readline
    end
    @@menu = menu
  end
end

describe '.get_menu' do
  before do
    Readline.stub(:readline).and_return('bar')
    Menu.new.get_menu
  end

  it 'should not set class var' do
    expect(Menu.menu).to be_nil
  end
end

这是完全做作的,可能实际上并没有运行,但你明白了......(我使用readline来完成制表符,但它与gets / stdin的问题相同)

关于gotva解决方案的一些细节

因为我需要最终设置'foo'以防止无限循环,所以我必须测试模拟而不是Menu.menu的结束值

Readline.stub(:readline).and_return('bar', 'par', 'foo')

expect(Readline).to have_received(:readline).exactly(3).times

2 个答案:

答案 0 :(得分:1)

我将设置变量的测试分开,并检查对.readline的调用是否被称为输入的次数。

例如

class Menu                                                                                                                                                                                                 
  attr_accessor :menu                                                                                                                                                                                      

  def get_menu                                                                                                                                                                                             
    menu = nil                                                                                                                                                                                             
    menu = Readline.readline until menu == 'foo'                                                                                                                                                           
    @menu = menu                                                                                                                                                                                           
  end                                                                                                                                                                                                      
end                                                                                                                                                                                                        

describe Menu do                                                                                                                                                                                           
  subject(:menu) { Menu.new }                                                                                                                                                                              
  describe '#get_menu' do                                                                                                                                                                                  

    it 'sets instance var' do                                                                                                                                                                                 
      Readline.stub(:readline).and_return('foo')                                                                                                                                                           
      menu.get_menu                                                                                                                                                                                        
      expect(menu.menu).to eq 'foo'                                                                                                                                                                        
    end                                                                                                                                                                                                    

    it 'calls readline once until "foo" is received' do                                                                                                                                                    
      Readline.stub(:readline).and_return('foo', 'two', 'three')                                                                                                                                           
      expect(Readline).to receive(:readline).exactly(:once)                                                                                                                                                
      menu.get_menu                                                                                                                                                                                        
    end                                                                                                                                                                                                    

    it 'calls readline thrice until "foo" is received' do                                                                                                                                                  
      Readline.stub(:readline).and_return('one', 'two', 'foo')                                                                                                                                             
      expect(Readline).to receive(:readline).exactly(3).times                                                                                                                                              
      menu.get_menu                                                                                                                                                                                        
    end                                                                                                                                                                                                    
  end                                                                                                                                                                                                      
end                                                          

答案 1 :(得分:0)

也许您正在寻找返回多个值的stub

请参阅此answer

例如

it 'should not set class var' do
  Readline.stub(:readline).and_return('bar', 'bar', 'bar')
  Menu.new.get_menu

  expect(Menu.menu).to be_nil
end

it 'should set class var' do
  Readline.stub(:readline).and_return('bar', 'bar', 'foo')
  Menu.new.get_menu

  expect(Menu.menu).to eq('foo')
end

但我发现另一个问题:你可以得到无限循环 - 小心。