2017-05-09 84 views
0

我想单元测试使用RSpec为回报率的方法和有一个方法是这样的:Ruby/Rails测试 - 范围之外的访问变量?

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进入该方法,而不是依赖它在其他地方填充(又名:这是代码味道?)?谢谢!

+0

存根'obj.save'引发一些错误,并检查'​​ActionMailer :: Base.deliveries.count'是否增加了一个。 –

回答

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

+0

所以我应该把它作为参数传递给'create_record'来开始?这主要是带走了吗?谢谢! – skaz

+0

是的。 – max

+0

提供的代码的另一个大问题是,您使用的是全部“rescue”语句,而没有提供您想要解救的异常。这掩盖了程序中的错误。 – max