I have written a Rails 3.1 engine with the namespace Posts. Hence, my controllers are found in app/controllers/posts/, my models in app/models/posts, etc. I can test the models just fine. The spec for one model looks like…
module Posts
describe Post do
describe 'Associations' do
it ...
end
… and everything works fine.
However, the specs for the controllers do not work. The Rails engine is mounted at /posts, yet the controller is Posts::PostController. Thus, the tests look for the controller route to be posts/posts.
describe "GET index" do
it "assigns all posts as @posts" do
Posts::Post.stub(:all) { [mock_post] }
get :index
assigns(:posts).should eq([mock_post])
end
end
which yields…
1) Posts::PostsController GET index assigns all posts as @posts
Failure/Error: get :index
ActionController::RoutingError:
No route matches {:controller=>"posts/posts"}
# ./spec/controllers/posts/posts_controller_spec.rb:16
I've tried all sorts of tricks in the test app's routes file… :namespace, etc, to no avail.
How do I make this work? It seems like it won't, since the engine puts the controller at /posts, yet the namespacing puts the controller at /posts/posts for the purpose of testing.
Best Answer
I'm assuming you're testing your engine with a dummy rails app, like the one that would be generated by enginex.
Your engine should be mounted in the dummy app:
In
spec/dummy/config/routes.rb
:My second assumption is that your engine is isolated:
In
lib/posts.rb
:I don't know if these two assumptions are really required, but that is how my own engine is structured.
The workaround is quite simple, instead of this
use this
The
:posts
symbol should be the name of your engine and NOT the path where it is mounted.This works because the get method parameters are passed straight to
ActionDispatch::Routing::RouteSet::Generator#initialize
(defined here), which in turn uses@named_route
to get the correct route fromRack::Mount::RouteSet#generate
(see here and here).Plunging into the rails internals is fun, but quite time consuming, I would not do this every day ;-) .
HTH