RSpec实例变量测试失败求助:无法保存用户输入
问题分析与修复
测试代码核心问题:执行顺序颠倒
你当前的测试是先获取实例变量,再调用方法,此时@name还未被赋值,自然是空字符串。正确逻辑应该是先执行get_names完成变量赋值,再获取变量做断言。
原方法的潜在bug
除测试顺序外,get_names方法本身存在几个问题:
- 使用未初始化的局部变量
name,会触发NameError - 判断
@player1 == ''逻辑错误,新实例的@player1初始值是nil而非空字符串 - 赋值时误用局部变量
name,而非实例变量@name
修复后的测试代码
describe Game do subject(:game_names) { described_class.new } describe '#get_names' do context 'when a user inputs name' do it 'saves in name instance variable' do # 模拟用户输入'joe' allow(game_names).to receive(:gets).and_return('joe') # 先执行方法完成赋值 game_names.get_names # 再获取实例变量并断言 name = game_names.instance_variable_get(:@name) expect(name).to eq 'joe' end end end end
修复后的get_names方法
def get_names while Player.players < 2 # 初始化实例变量,避免未定义错误 @name ||= '' while @name.length <= 2 puts 'Each player must choose a name' print 'Enter a name: ' @name = gets.chomp end unless @name == '' # 判断@player1是否未初始化(nil),而非是否等于空字符串 @player1.nil? ? @player1 = Player.new(@name) : @player2 = Player.new(@name) @name = '' puts 'Name have been saved successfully' end end end
额外说明
- 如果
Player.players初始值为0,需要模拟两次输入才能退出外层循环,否则测试会卡在循环内。可补充模拟第二次输入:allow(game_names).to receive(:gets).and_return('joe', 'bob') - 建议给
Game类的@player1和@player2设置默认值(如nil),避免判断逻辑出错。
内容的提问来源于stack exchange,提问作者Ruiyot Abby
相关产品推荐
相关产品推荐

