RSpec: 在示例中从块内访问 `let` 定义
RSpec: Accessing a `let` definition from within a block in an example
我在 RSpec 测试中基本上有这个设置:
RSpec.describe Something do
describe '#something' do
let(:my_var) { 'some data' }
let(:my_object) { MyObject.new }
it 'example' do
my_object.instance_eval { @my_inst_var = my_var } # ERROR here
end
end
end
这导致
NameError: #MyObject:0x5d14e99e
的未定义局部变量或方法“myvar”
我明白,在 my_object
的执行上下文中,Ruby 不知道如何处理 RSpec 中 let
构造的“魔法”。我知道我可以在这里使用“普通变量”而不是 let
,我也可以这样做(这就是我目前解决问题的方式):
# This works of course
it 'example' do
mv = my_var # Forces the let(:my_var) to be evaluated
my_object.instance_eval { @my_inst_var = mv }
end
问题:假设我确实想在示例中使用 let
和 `instance_eval,是否有更好的方法?
有多种方法可以做到这一点。使用 instance_eval 在我的列表中并不高。
如果 attr_accessor 有意义,您肯定应该这样做:
class Something
attr_accessor :my_inst_var
end
it 'example' do
my_object.my_inst_var = my_var
end
如果您不想污染您的对象 public 方法,我认为以下选项比 instance_eval.
更干净
it 'example' do
my_object.instance_variable_set :@my_instance_var, my_var
end
改用instance_exec
——它允许您将参数传递到块的范围内:
my_object.instance_exec(my_var) { |v| @my_inst_var = v }
或者,您可以通过 instance_variable_set
:
设置实例变量
my_object.instance_variable_set(:@my_inst_var, my_var)
虽然以上两种方法都有效,但以这种方式改变对象的状态可能会导致脆弱的测试。您应该考虑更改对象,以便更容易测试。 (加一个setter或初始化时传值)
我在 RSpec 测试中基本上有这个设置:
RSpec.describe Something do
describe '#something' do
let(:my_var) { 'some data' }
let(:my_object) { MyObject.new }
it 'example' do
my_object.instance_eval { @my_inst_var = my_var } # ERROR here
end
end
end
这导致
NameError: #MyObject:0x5d14e99e
的未定义局部变量或方法“myvar”我明白,在 my_object
的执行上下文中,Ruby 不知道如何处理 RSpec 中 let
构造的“魔法”。我知道我可以在这里使用“普通变量”而不是 let
,我也可以这样做(这就是我目前解决问题的方式):
# This works of course
it 'example' do
mv = my_var # Forces the let(:my_var) to be evaluated
my_object.instance_eval { @my_inst_var = mv }
end
问题:假设我确实想在示例中使用 let
和 `instance_eval,是否有更好的方法?
有多种方法可以做到这一点。使用 instance_eval 在我的列表中并不高。 如果 attr_accessor 有意义,您肯定应该这样做:
class Something
attr_accessor :my_inst_var
end
it 'example' do
my_object.my_inst_var = my_var
end
如果您不想污染您的对象 public 方法,我认为以下选项比 instance_eval.
更干净it 'example' do
my_object.instance_variable_set :@my_instance_var, my_var
end
改用instance_exec
——它允许您将参数传递到块的范围内:
my_object.instance_exec(my_var) { |v| @my_inst_var = v }
或者,您可以通过 instance_variable_set
:
my_object.instance_variable_set(:@my_inst_var, my_var)
虽然以上两种方法都有效,但以这种方式改变对象的状态可能会导致脆弱的测试。您应该考虑更改对象,以便更容易测试。 (加一个setter或初始化时传值)