bploetz / versionist

A plugin for versioning Rails based RESTful APIs.
MIT License
971 stars 51 forks source link

No route matches error when testing in RSpec #22

Closed starkovv closed 12 years ago

starkovv commented 12 years ago

app/controllers/v1/sessions_controller.rb:

class V1::SessionsController < V1::BaseController
  def index
    render :json => {text: 'hello'}
  end
end

config/routes.rb:

MyApp::Application.routes.draw do
  api_version(:module => 'V1', :header => 'X-Version', :value => '1', :defaults => {:format => :json}, :default => true) do
    resources :sessions
  end
end

spec/controllers/v1/sessions_controller_spec.rb:

require 'spec_helper'

describe V1::SessionsController do
  it 'should work' do
    get :index
  end
end

$ bundle exec rspec spec/controllers/v1/sessions_controller_spec.rb:

V1::SessionsController
  should work (FAILED - 1)

Failures:

  1) V1::SessionsController should work
     Failure/Error: get :index
     ActionController::RoutingError:
       No route matches {:controller=>"v1/sessions"}
     # ./spec/controllers/v1/sessions_controller_spec.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.01906 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/controllers/v1/sessions_controller_spec.rb:4 # V1::SessionsController should work

$ curl -H 'X-Version: 1' http://127.0.0.1:3000/sessions:

{"text":"hello"}

$ curl http://127.0.0.1:3000/sessions:

{"text":"hello"}

I would be glad if community help me with that. What I'm doing wrong?

starkovv commented 12 years ago

After 4 hours I found the solution.

config/routes.rb:

MyApp::Application.routes.draw do
  api_version(:module => 'v1', :header => 'X-Version', :value => '1', :defaults => {:format => :json}, :default => true) do
    resources :sessions
  end
end

It is required to set :module in lowercase.

I think it needs to update README in this part.

Issue closed.

bploetz commented 12 years ago

No, that's not the fix. If you use the header strategy, then you need to use RSpec request specs, not controller specs.

See https://github.com/bploetz/versionist/issues/17

I will add this to the README as it keeps tripping people up.

starkovv commented 12 years ago

I returned config/routes.rb to the previous version (now it's in UPPERCASE again):

MyApp::Application.routes.draw do
  api_version(:module => 'V1', :header => 'X-Version', :value => '1', :defaults => {:format => :json}, :default => true) do
    resources :sessions
  end
end

And I've tried the example you showed https://github.com/bploetz/versionist/issues/17:

require 'spec_helper'

describe V1::SessionsController do
  describe 'create new customer' do
    it "should work" do
        get '/sessions', {}, {'X-VERSION' => '1'} do
          assert_response 200
        end
    end
  end
end

And when I do

$ bundle exec rspec spec/controllers/v1/sessions_controller_spec.rb

I still have an error:

V1::SessionsController
  should work (FAILED - 1)

Failures:

  1) V1::SessionsController should work
     Failure/Error: get :index, nil, {'X-Version' => '1'}
     ActionController::RoutingError:
       No route matches {:controller=>"v1/sessions"}
     # ./spec/controllers/v1/sessions_controller_spec.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.02195 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/controllers/v1/sessions_controller_spec.rb:4 # V1::SessionsController should work
bploetz commented 12 years ago

you have to put the test in spec/requests

starkovv commented 12 years ago

I put it to spec/requests.

Now test passed. But.

If I change it to something unexpected:

require 'spec_helper'

describe V1::SessionsController do
  describe 'create new customer' do
    it "should work" do
        get '/sessions', {}, {'X-VERSION' => '1'} do
          assert_response 123456
        end
    end
  end
end

It still pass. It is strange, maybe I missed something?

starkovv commented 12 years ago

Update.

This version works as expected:

require 'spec_helper'

describe V1::SessionsController do
  describe 'create new customer' do
    it "should work" do
        get '/sessions', {}, {'X-VERSION' => '1'}
        response.code.should == '200'
    end
  end
end

Above is passed. And below is red:

require 'spec_helper'

describe V1::SessionsController do
  describe 'create new customer' do
    it "should work" do
        get '/sessions', {}, {'X-VERSION' => '1'}
        response.code.should == '123456'
    end
  end
end

I use webrat, probably it somehow influences.

bploetz commented 12 years ago

I added a section to the README about testing

starkovv commented 12 years ago

Thank you for your assistance with this issue. And thank you for such a gem :-)

I have just one question, is there any special tricks I should know when testing with path strategy?

bploetz commented 12 years ago

Since the path strategy are really just normal URLs with a prefix, everything should just work as you expect without the need for any special magic.

starkovv commented 12 years ago

Is it possible to rspec controllers if I use versionist gem in my project?

config/routes.rb:

MyApp::Application.routes.draw do
  api_version(:module => 'V1', :path => 'v1') do
    resources :sessions
  end
end

spec/controllers/v1/sessions_controller_spec.rb:

require 'spec_helper'

describe V1::SessionsController do
  it 'should work' do
    get '/v1/index'
  end
end

$ bundle exec rspec spec/controllers/v1/sessions_controller_spec.rb:

V1::SessionsController
  should work (FAILED - 1)

Failures:

  1) V1::SessionsController should work
     Failure/Error: get '/v1/index'
     ActionController::RoutingError:
       No route matches {:controller=>"v1/sessions", :action=>"/v1/index"}
     # ./spec/controllers/v1/sessions_controller_spec.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.02048 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/controllers/v1/sessions_controller_spec.rb:4 # V1::SessionsController should work
bploetz commented 12 years ago

That route in your spec doesn't look right. It should be something like GET /v1/sessions. Run rake routes to see for sure.