Ruby / Rails测试 - 访问范围之外的变量?

时间:2017-05-09 11:18:52

标签: ruby-on-rails ruby testing rspec

我想使用rspec对RoR进行单元测试,并使用如下方法:

def create_record(obj, params)
    begin
      obj.add_attributes(params)
      result = obj.save
    rescue
      MyMailer.failed_upload(@other_var, obj.api_class_name, params).deliver_now
    end
end

create_record永远不会直接调用,而是通过另一种适当填充@other_var的方法调用。

我应该如何测试代码以确保正确调用MyMailer?我应该将@other_var传递给方法,而不是依赖它在其他地方填充(也就是说:这是代码味道吗?)?谢谢!

1 个答案:

答案 0 :(得分:0)

在Ruby中,您可以使用Object#instance_variable_set来设置任何实例变量。

RSpec.describe Thing do 
  describe "#create_record" do
    let(:thing) do
      t = Thing.new
      t.instance_variable_set(:@other_var, "foo")
      t
    end
    # ...
  end
end 

这完全绕过了任何封装,这意味着instance_variable_set的使用可以被视为代码气味。

另一种选择是使用RSpecs模拟和存根设施,但是对测试中的实际对象进行存根也是一种代码味道。

您可以通过将依赖项作为参数或构造函数注入传递来避免这种情况:

class Thing
  attr_accessor :other_var

  def initialize(other_var: nil)
     @other_var = other_var
  end

  def create_record(obj, attributes)
     # ...
  end
end

一个好的模式是service objects