2012-01-24 17 views
9

Funkcja force_ssl w szynach 3.1 jest na stałe zakodowana, aby ignorować środowisko programistyczne, ale nie testować. To daje mi błędy przekierowania w moich (minimalistycznych) testach. Czy rozwiązaniem jest skonfigurowanie mojego serwera testowego tak, aby obsługiwał ssl (jeśli tak, to w jaki sposób?). Jeśli nie, czy powinienem małpować patch force_ssl, aby ignorować żądania w teście?W jaki sposób ludzie testują szyny 3.1 + force_ssl?

def force_ssl(options = {}) 
     host = options.delete(:host) 
     before_filter(options) do 
      if !request.ssl? && !Rails.env.development? 
      redirect_options = {:protocol => 'https://', :status => :moved_permanently} 
      redirect_options.merge!(:host => host) if host 
      flash.keep 
      redirect_to redirect_options 
      end 
     end 
    end 

EDIT Znaleźliśmy ten łańcuch, który potwierdza, inni, że to problem, ale nie wygląda jak tam jest zaangażowana fix jeszcze: https://github.com/rails/rails/pull/2630

Odpowiedz

18

Inną opcją zamiast małpy łatanie całej aplikacji jest po prostu zastąpić force_ssl w swoim apartamencie testowym sam. Na przykład, w test/test_helper.rb można dodać to:

# We don't want SSL redirects in our test suite 
module ActionController::ForceSSL::ClassMethods 
    def force_ssl(options = {}) 
    # noop 
    end 
end 
+1

to wydaje się lepszym podejściem – spike

+3

Mam to na końcu z mojego pliku test_helper.rb, a wszystko jest dobrze działające specyfikacje ze sporkami. Ale samo uruchomienie rspec zdaje się ignorować to. Każdy pomysł, dlaczego? – Owen

4

to co skończyło się robi po ostatnim uaktualnieniu do Rails 3.1 i przejście na filtr force_ssl. Monkey patch na ratunek!

w nowym pliku w config/initializers/ignore_force_ssl_in_test.rb

module ActionController 
    module ForceSSL 
    module ClassMethods 
     def force_ssl(options = {}) 
     before_filter(options) do 
      if !request.ssl? && !Rails.env.development? && !Rails.env.test? 
      redirect_to :protocol => 'https://', :status => :moved_permanently 
      end 
     end 
     end 
    end 
    end 
end 
+0

Świetnie, to działa dla mnie. Przyjmuję twoją odpowiedź, ale jeśli/kiedy to zostanie włączone do szyn, wrócę i dodaję notatkę – spike

+0

To pominie wszelkie parametry w adresie URL, jestem prawie pewien. Spójrz na ten link, aby obejść to: http://stackoverflow.com/questions/11252910/rails-redirect-to-https-while-keeping-all-parameters –

16

Oto inne podejście, jeśli nie chcą zadzierać z małpa-łatanie ... można użyć przed filtrem. To rspec nie MiniTest składnia, ale masz pomysł:

before(:each) do 
    request.env["rack.url_scheme"] = "https" 
end 

Ten przekonuje kontroler że dostał żądania SSL.

Zaletą takiego podejścia jest to, że można napisać test, aby upewnić się, że kontroler wymaga protokołu SSL. :)

+0

Gdzie to położyłeś? Otrzymuję 'NameError: niezdefiniowana zmienna lokalna lub metoda' request'' –

4

Jeśli jesteś zainteresowany testowaniem z różnym SSL, zrobiłem to podczas konfiguracji testu funkcjonalnego.

def setup 
    @request.env['HTTPS'] = 'on' 
end 
3

Co pracował dla mnie jest podobny do Kelly Sutton's. I łatki małpa force_ssl ignorować żądania SSL w środowisku testowym, inaczej używać oryginalnego realizację szyn:

module ActionController 
    module ForceSSL 
    module ClassMethods 
     alias_method :original_force_ssl, :force_ssl 

     def force_ssl(options = {}) 
     unless Rails.env.test? 
      original_force_ssl(options) 
     end 
     end 
    end 
    end 
end 
+0

Podejście Ryana wydaje się podobne do tego, z tym że jego kod działa tylko w środowisku testowym. Myślę, że umieszczenie jego bloku w teście.rb jest lepsze niż uruchomienie bloku we wszystkich środowiskach? – spike

+0

Podejście Ryana nie zadziałało, ponieważ 'force_ssl' jest metodą klasową. Spec_helper.rb załaduje najpierw środowisko Railsowe, potem twój kod, efektywnie wywołując oryginalny 'force_ssl', a nie ten zdefiniowany w spec_helper.rb – gylaz

+0

To jest jedyne rozwiązanie, które zostało tu napisane. Railsy 3.2.13 i Rspec z Capybara i Selenium. Dzięki! – n8gard

0

Możesz wykonywać połączenia testowe do aplikacji za pomocą ssl!

  • wykorzystanie pełnego uri z protokołem https://eample.org/my/route/here w get 'https://eample.org/my/route/here'
  • lub wykorzystać https!(true) i https!(false) dynamicznie zmieniać zachowanie w test integracyjny

    https!(true) 
    get "/users" 
    https!(false) 
    

regulatora nie trzeba korzystać z protokołu SSL, ponieważ (jak sądzę) bezpośrednio wywołują akcję jako metodę, bez routingu i innych transferów.

0

Dokumenty Rails zalecają użycie: ssl_configured? z wywołaniem force_ssl. Możesz następnie wykonać:

def ssl_configured? 
    !Rails.env.development? && !Rails.env.test? 
    end 

Bez konieczności opatrywania małpką, jak wskazuje oficjalna odpowiedź.

Powiązane problemy