2017-05-09 4 views
0

Ich mag Unit-Test ein Verfahren mit rspec für RoR und habe eine Methode wie folgt:Ruby/Rails-Test - Zugriffsvariable außerhalb des Gültigkeitsbereichs?

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 wird nie direkt aufgerufen, sondern durch ein anderes Verfahren, das in geeigneter Weise in @other_var füllt.

Wie soll ich mich über den Code zu testen sicher MyMailer machen richtig genannt wird? Sollte ich @other_var in die Methode eingeführt haben, anstatt darauf zu vertrauen, dass sie anderswo ausgefüllt wird (aka: ist das ein Code-Geruch?)? Vielen Dank!

+0

Stub 'obj.save' einige Fehler zu heben und überprüfen, ob' Action :: Base.deliveries.count' um eins erhöht wird. –

Antwort

0

In Ruby können Sie Object#instance_variable_set verwenden jede Instanzvariable zu setzen.

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 

Dies umgeht vollständig jede Einkapselung was bedeutet, dass die Verwendung von instance_variable_set kann ein Code Geruch in Betracht gezogen werden.

Eine weitere Alternative ist RSpecs spöttisch und Anstoßen Einrichtungen zu verwenden, aber das eigentliche Objekt im Test Anstoßen ist auch ein Code Geruch.

Sie können dies vermeiden, indem die Abhängigkeit als Parameter oder durch Konstruktor Injektion vorbei:

class Thing 
    attr_accessor :other_var 

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

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

Ein gutes Muster hierfür ist service objects.

+0

Also hätte ich das als Parameter an create_record übergeben sollen? Ist das der wichtigste Weg? Vielen Dank! – skaz

+0

Ja, ziemlich. – max

+0

Ein weiteres großes Problem mit dem Code versehen ist, dass Sie eine allumfassende 'rescue' Anweisung verwenden, ohne die Ausnahmen vorausgesetzt, Sie retten wollen. Dies maskiert Fehler im Programm. – max

Verwandte Themen