2013-04-14 19 views
35
class TestController < AplicationController 
    #.... 

    private 

    def some_method 
    unless @my_variable.nil? 
     #... 
     return true 
    end 
    end 
end 

chcę testu some_method bezpośrednio kontrolera specyfikacji:rspec: Jak przypisać zmiennej instancji kontrolera w specyfikacji

require 'spec_helper' 

describe TestController do 
    it "test some_method" 
    phone = Phone.new(...) 
    controller.assign(:my_variable,phone) #does not work 
    controller.send(:some_method).should be_true 
    end 
end 

Jak mogę ustawić TestController instancję zmiennej @my_variable od kontrolera specyfikacji?

Odpowiedz

53

Podczas testowania prywatnych metod w kontrolerach, zamiast używać send, zazwyczaj używam anonymous controller, ponieważ nie chcę wywoływać bezpośrednio metody prywatnej, ale interfejsu do prywatnej metody (lub, w poniższym teście, skutecznie ograniczającego ten interfejs) . Tak więc, w przypadku, być może coś takiego:

require 'spec_helper' 

describe TestController do 
    controller do 
    def test_some_method 
     some_method 
    end 
    end 

    describe "a phone test with some_method" do 

    subject { controller.test_some_method } 

    context "when my_variable is not nil" do 
     before { controller.instance_variable_set(:@my_variable, Phone.new(...)) } 
     it { should be_true } 
    end 

    context "when my_variable is nil" do 
     before { controller.instance_variable_set(:@my_variable, nil) } 
     it { should_not be_true } # or should be_false or whatever 
    end  
    end 
end 

Jest jakaś dobra dyskusja w kwestii bezpośrednio testowania metod prywatnych w this StackOverflow Q&A, które kołysały mnie do korzystania anonimowe kontrolerów, ale Twoja opinia może się różnić.

+1

Dziękujemy @ Paul za dobre rozwiązanie. – ole

2

Nie sądzę, że chcesz uzyskać dostęp do zmiennej instancji z kontrolera spec, ponieważ specyfikacja powinna przetestować zachowanie, ale zawsze możesz użyć metody prywatnej. W Twoim przypadku powinno to być coś takiego (w tym przykładzie nie ma więc większego sensu):

describe TestController do 
    it "test some_method" 
    phone = Phone.new(...) 
    controller.stub(:some_method).and_return(true) 
    controller.send(:some_method).should be_true 
    end 
end 

Jeśli nie jest to co szukasz spojrzeć na to: How to set private instance variable used within a method test?

0

instance_eval jest stosunkowo czysta droga do osiągnięcia tego celu:

describe TestController do 
    it "test some_method" do 
    phone = Phone.new(...) 
    controller.instance_eval do 
     @my_variable = phone 
    end 
    controller.send(:some_method).should be_true 
    end 
end 

W tym przypadku, przy użyciu do...end na instance_eval jest przesadą, a te trzy linie mogą być skrócone do:

controller.instance_eval {@my_variable = phone} 
Powiązane problemy