Skip to content
This repository

Unit test with underscore namespace provoque "No route matches" #9

Closed
nicolas-brousse opened this Issue · 17 comments

2 participants

Nicolas Brousse Brian Ploetz
Nicolas Brousse

I start unit test implementation in my REST Api application.

So, I have a class named like this : Api::V0_1_0::TestController

class Api::V0_1_0::TestController < Api::V0_1_0::BaseController

  def test
    respond_with({
      :message => "done"
    })
  end

end

routes.rb (without all routes, but just the necessary):

MyApp::Application.routes.draw do

  # -----------------------------------------------------------------------------------------------------------------------------------------
  # ApiVersions
  #
  scope :module => "api",
        :defaults => {:format => "json"} do

    # ---------------------------------------------------------------------------------------------------
    # V0.1.0
    # Default version
    #
    api_version :module => "V0__1__0",
                :header => "X-Version", :value => "0.1.0" do

      # Test controller
      get "/test" => "test#test"
    end
    # ---------------------------------------------------------------------------------------------------

    # ---------------------------------------------------------------------------------------------------
    # V0.1.1
    # Default version
    #
    api_version :module => "V0__1__1",
                :header => "X-Version", :value => "0.1.1" do

      # Test Controller
      get "/test" => "test#test"

  end
  # -----------------------------------------------------------------------------------------------------------------------------------------



  # -----------------------------------------------------------------------------------------------------------------------------------------
  # ActiveAdmin routes
  #
  ActiveAdmin.routes(self)
  devise_for :admin_users, ActiveAdmin::Devise.config
  # -----------------------------------------------------------------------------------------------------------------------------------------


end

Functional test file :

class Api::V0_1_0::TestControllerTest < ActionController::TestCase

  test "should get test" do
    get :test
    assert_response :success
  end
end

When I launch rake test:functionals.
I have this error :

No route matches {:controller=>"api/v0_1_0/test", :action=>"test"}

And when I launch rake routes, I have :

test GET  /test(.:format)   {:format=>"json", :controller=>"api/V0__1__0/test", :action=>"test"}

With double underscore for V0__1__0 and not V0_1_0.

I don't know how resolve this problem.

(I've try with rspec and I have the same problem).

Brian Ploetz
Owner

What version of Rails and Versionist are you using?

Nicolas Brousse

I'm sorry,

I use :

ruby  - 1.9.3-p0
rails - 3.1.4
versionist - 0.1.3
Brian Ploetz
Owner

Thanks. I'm trying to reproduce this locally. Stay tuned.....

Brian Ploetz
Owner

Just curious, if you start your server and do...

curl -H "X-Version: 0.1.0" http://localhost:3000/test.json

...do you get the correct "done" response?

Nicolas Brousse

Yes, it works correctly.
I use your gem for a month, and I never had a problem with the routes before.

In my terminal:

Started GET "/test.json" for 127.0.0.1 at 2012-04-24 18:55:49 +0200
  Processing by Api::V0_1_0::TestController#test as JSON
Completed 200 OK in 1963ms (Views: 4.5ms | ActiveRecord: 0.0ms
Brian Ploetz
Owner

Great, thanks. Will report back here when I'm able to reproduce this.

(FYI, this helped me find this bug as well: #10)

:-)

Brian Ploetz
Owner

Ah, I see. You don't have a default API version defined, and you're not passing in the X-Version header in your request, so Rails can't find the route (which is correct). You need to pass the header in the test request to get it to find the route. I can't figure out how to get this to work in functional tests, but here's what the integration test looks like:

> more test/integration/api/v0_1_0/test_controller_test.rb 

require 'test_helper'

class Api::V0_1_0::TestControllerTest < ActionDispatch::IntegrationTest

  test "should get test" do
    get '/test', nil, {"X-Version" => "0.1.0"}
    assert_response :success
    assert_equal @response.body, "done"
  end
end

Versionist should generate integration tests/request specs to facilitate testing when using the header strategy. I've filed #11 to add that.

Brian Ploetz bploetz closed this
Nicolas Brousse

Okey, I see for the header.
But even without a default version specified, my API worked well and found the right route.
And I have a route in a particular version, so I couldn't test it.

Brian Ploetz
Owner

Not sure I understand. When you say "my API worked well and found the right route", are you saying that when you run the server and do a GET /test without specifying the X-Version header (which is what your test is doing) you get a response back? Assuming you have just what you have above in your config/routes.rb, you should get a routing error, which is what you're getting in your test (and what I get locally when I reproduced this setup) when you don't specify an X-Version header matching one of your configured api versions.

Specifying a version:

Client:
> curl -H "X-Version: 0.1.0" http://localhost:3000/test
done

Server:
Started GET "/test.json" for 127.0.0.1 at 2012-04-24 13:55:00 -0400
  Processing by Api::V0_1_0::TestController#test as JSON
Rendered text template (0.0ms)
Completed 200 OK in 26ms (Views: 25.8ms | ActiveRecord: 0.0ms)

Not specifying a version:

Client:
curl http://localhost:3000/test

Server:
Started GET "/test" for 127.0.0.1 at 2012-04-24 13:56:18 -0400

ActionController::RoutingError (No route matches [GET] "/test"):
Nicolas Brousse

When I test with rspec, I have :

rails g rspec:controller Api::V0__1__0::Post
return :
create spec/controllers/api/v0__1__0/posts_controller_spec.rb

> more spec/controllers/api/v0__1__0/posts_controller_spec.rb 

require 'spec_helper'

describe Api::V0_1_0::PostsController do

end

And with other writen:

rails g rspec:controller Api::V0_1_0::Post
create spec/controllers/api/v0_1_0/posts_controller_spec.rb

> more spec/controllers/api/v0_1_0/posts_controller_spec.rb

require 'spec_helper'

describe Api::V010::PostsController do

end

Do not you think there is a concern the underscore interpretation?

Brian Ploetz
Owner

While I can't speak for the rspec generators, it looks like it doesn't do the right thing for underscores in module names. If you use the versionist generators they will take care of creating the tests for you, accounting for underscores correctly. See the Readme for examples.

Nicolas Brousse

To answer your comment.

I'm just saying that if in my routes.rb file I don't precise default version. And when a do a request to my server with /test.json and X-Version: 0.1.0 it works.

So, Rails found the good route without default version specified in my routes.rb file.

But, sure, if I dont precise X-VersionI receive an Exception for ActionController::RoutingError.

So if we follow this reasoning it should work correctly with the test units, no?
I feel that when the units test generate the :controller value for get '/test' (for example), it can't generate the good value with the double underscore. But why ? :P

Nicolas Brousse

Sure. I've just test the two options.
And since rspec is not defined by default in my local, versionist generators does not generate rspec file but those basics unit testing files.

Brian Ploetz
Owner

Versionist's generators figure out which test files to generate based on the value of the configured test_framework in config/application.rb. If you want rspec, add:

config.generators do |g|
  g.test_framework :rspec
end
Nicolas Brousse

When I use rails console for test underscore function and camelize function, I have this :

1.9.3p125 :018 > "V0__1__0".underscore.camelize
 => "V0_1_0" 

So I suppose, when ActionController::TestCase try to generate the route, Rails don't add the double underscore.
I suppose that join your issue on rails github repository.

Brian Ploetz
Owner

I'm not clear on what problem you're having. Tests (both functional and integration) work just fine in Rails 3.1 when there are underscores in the module names. As noted above, if you're intent on using rspec's generators to generate these tests, it looks like rspec doesn't deal with underscores correctly, so you'll have to massage the generated files/module names manually to fix them. Versionist's generators take care of this detail for you (new_api_version and new_controller). I re-created your example app noted above locally, and all of the tests work just fine.

Nicolas Brousse

I'm sorry it's possible that I've forgot something.
It's the first time I do unit test in Rails. And I develop in rails only for 1 year.

I have create an integration test and I define a default api version, the test works successfully.
But I don't succeed in making a functional test correctly. :(

Thank you for your patience and your speed of answer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.