RSpec中instance_variable_set不生效?求原因与解决办法
问题分析与解决办法
嘿,这个问题的核心是你搞混了类的实例变量和对象实例的实例变量,我给你一步步拆解:
为什么测试不通过?
你用Script.instance_variable_set(:@timeZonesCache, ...)设置的是Script这个类对象的实例变量,但my_timezone_description方法里访问的@timeZonesCache是每个Script实例自己的实例变量——这俩完全是不同的东西!
简单说:
Script本身是一个类对象,它的实例变量属于类,不会被所有实例自动共享- 每次调用
Script.new都会创建一个全新的Script实例,这个实例有自己独立的@timeZonesCache(如果没在initialize里初始化,默认就是nil)
所以你用Script.instance_variable_get能拿到类上的缓存,但新创建的实例的@timeZonesCache根本没被设置,测试自然失败。
两种解决思路
思路1:如果缓存应该是类级别的(所有实例共享)
如果@timeZonesCache本来就设计成所有Script实例共享的缓存,那应该把它改成类级别的变量,同时提供访问方式:
修改原代码:
class Script # 初始化类实例变量 @timeZonesCache = {} # 提供类方法访问缓存 def self.time_zones_cache @timeZonesCache end def initialize end def my_timezone_description(timeZoneId) # 访问类的缓存,而不是实例自己的 self.class.time_zones_cache[timeZoneId] end end
对应的测试代码:
it 'gets the timezone description' do Script.time_zones_cache[123] = '+01:00' expect(Script.new.my_timezone_description(123)).to eq '+01:00' end
思路2:给具体的测试实例设置变量
如果@timeZonesCache就是每个实例自己的变量,那你应该给Script.new创建的那个具体实例设置变量,而不是给类设置:
修改测试代码:
it 'gets the timezone description' do # 先创建实例 script_instance = Script.new # 给这个实例设置它自己的@timeZonesCache script_instance.instance_variable_set(:@timeZonesCache, {123 => '+01:00'}) expect(script_instance.my_timezone_description(123)).to eq '+01:00' end
这种方式不需要修改原代码,适合只是为了测试当前方法的场景。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

