Techioz Blog

Rack/Test を使用して Sinatra リダイレクトをテストするにはどうすればよいですか?アプリは動作するが、テストが動作しない

概要

おそらくこれを回避する方法があるでしょう。そうでない場合、Rack/Test は役に立たないでしょう。ここで機能させるには何をすべきか誰か教えてもらえますか?

(編集: 最終的に達成したいのは、ステータスではなく、最終的にどのページを取得するかをテストすることです。テストでは、last_response オブジェクトはアプリに存在しないページを指しており、実際に取得するページではありません。実行すると取得されます。)

アプリの例:

require 'sinatra'
require 'haml'

get "/" do
  redirect to('/test')
end

get '/test' do
  haml :test
end

これはご想像どおりに機能します。 「/」または「/test」に移動すると、views/test.haml の内容が取得されます。

しかし、このテストは機能しません。

require_relative '../app.rb'
require 'rspec'
require 'rack/test'

describe "test" do
  include Rack::Test::Methods

  def app
    Sinatra::Application
  end

  it "tests" do
    get '/'
    expect(last_response.status).to eq(200)
  end
end

テストを実行すると次のことが起こります。

1) test tests
   Failure/Error: expect(last_response.status).to eq(200)

     expected: 200
          got: 302

last_response.inspect は次のようになります。

#<Rack::MockResponse:0x000000035d0838 @original_headers={"Content-Type"=>"text/html;charset=utf-8", "Location"=>"http://example.org/test", "Content-Length"=>"0", "X-XSS-Protection"=>"1; mode=block", "X-Content-Type-Options"=>"nosniff", "X-Frame-Options"=>"SAMEORIGIN"}, @errors="", @body_string=nil, @status=302, @header={"Content-Type"=>"text/html;charset=utf-8", "Location"=>"http://example.org/test", "Content-Length"=>"0", "X-XSS-Protection"=>"1; mode=block", "X-Content-Type-Options"=>"nosniff", "X-Frame-Options"=>"SAMEORIGIN"}, @chunked=false, @writer=#<Proc:0x000000035cfeb0@/home/jonea/.rvm/gems/ruby-1.9.3-p547@sandbox/gems/rack-1.5.2/lib/rack/response.rb:27 (lambda)>, @block=nil, @length=0, @body=[]>

Rack/Test がリダイレクトに「http://example.org」を挿入することを勝手に決定しただけなのでしょうか?

解決策

@sirl33tname が指摘しているように、リダイレクトは依然としてリダイレクトであるため、期待できる最高のステータスは 200 ではなく 302 です。リダイレクトの最後に適切なページが得られたかどうかをテストしたい場合は、「ok?」をテストする必要があります。ステータスではありません。

ただし、最終的にどのような URL になるかをテストしたい場合は、もう少し作業する必要があります。Rack/Test は基本的にモック システム (原文どおり) であり、リダイレクト時にページのモックを返すためです。実際のページ。

しかし、これは、follow_redirect! を使用して簡単にオーバーライドできることがわかりました。

テストは次のようになります。

it "tests" do
  get '/'
  follow_redirect!
  expect(last_response.status).to be_ok

  # ...and now I can test for the contents of test.haml, too...
  expect(last_response.body).to include('foo')
end

そしてそれが仕事をするのです。