I have a controller spec looking like this:
# config_controller_spec.rb
require "spec_helper"
describe Api::V4::ConfigController, type: :controller do
let(:parsed_response) { response.body.to_json }
describe 'GET app_config' do
it "renders successfully" do
get :app_config
expect(response).to be_success
expect(parsed_response).to eq("{key: val}")
end
end
end
When I run it however, I get:
ActionController::UrlGenerationError:
No route matches {:action=>"app_config", :controller=>"api/v4/config"}
I don't under stand why. I googled around and figured that if I add: use_route: :config
to the get call like so: get :app_config, use_route: :config
, then it works for some reason, though I don't understand why? But when appending that, I get the following deprecation error:
DEPRECATION WARNING: Passing the `use_route` option in functional tests are deprecated. Support for this option in the `process` method (and the related `get`, `head`, `post`, `patch`, `put` and `delete` helpers) will be removed in the next version without replacement.
Functional tests are essentially unit tests for controllers and they should not require knowledge to how the application's routes are configured. Instead, you should explicitly pass the appropiate params to the `process` method.
Previously the engines guide also contained an incorrect example that recommended using this option to test an engine's controllers within the dummy application.
That recommendation was incorrect and has since been corrected.
Instead, you should override the `@routes` variable in the test case with `Foo::Engine.routes`. See the updated engines guide for details.
Here is my controller:
# config_controller.rb
class Api::V4::ConfigController < Api::V4::BaseController
def app_config
render json: Api::V6::Config.app_config, root: false
end
end
And routes:
# routes.rb
MyApp::Application.routes.draw do
constraints subdomain: /\Awww\b/ do
namespace :api, defaults: {format: 'json'} do
get 'app_config' => 'config#app_config'
end
end
end
Use a request spec instead of a controller spec:
describe "Api V4 Configuration", type: :request do
let(:json) { JSON.parse(response.body) }
subject { response }
describe 'GET app_config' do
before { get "/api/v4/app_config" }
it { should be_successful }
it "has the correct contents" do
expect(json).to include(foo: "bar")
end
end
end
One of biggest changes with Rails 5 was the depreciation of ActionController::TestCase
(which RSpec controller specs wrap) in favor of integration tests. Thus using request specs is a more future proof solution - using less abstraction also means that your specs will cover routing properly as well.
Also you don't seem to be nesting your routes properly:
# routes.rb
MyApp::Application.routes.draw do
constraints subdomain: /\Awww\b/ do
namespace :api, defaults: {format: 'json'} do
namespace :v4 do
get 'app_config' => 'config#app_config'
end
end
end
end
See: