I have a weird issue when creating a controller spec for a namespaced controller when there also is a global controller with the same name.
The controller names are HomeController
and Backend::HomeController
.
Note that I have not yet created the file app/controllers/backend/home_controller.rb
, only the global controller exists app/controllers/home_controller.rb
Therefore I expect the test to explode with errors, but it does not. It passes, all green and happy.
My spec looks like this
#spec/controllers/backend/home_controller_spec.rb
require 'rails_helper'
RSpec.describe Backend::HomeController, type: :controller do
before do
user = FactoryGirl.create(:user)
allow(controller).to receive(:authenticate_user!).and_return(true)
allow(controller).to receive(:current_user).and_return(user)
end
describe "GET #index" do
it "returns http success" do
get :index
expect(response).to have_http_status(:success)
end
end
end
However if I change the name in my global HomeController
to something else, e.g NotMyHomeController
the test fails with errors saying
Unable to autoload constant HomeController, expected app/controllers/home_controller.rb to define it
Which makes me suspect that Rspec doesn't bother with the "Backend" part in the Rspec.describe
function.
Am I doing something wrong or am I missing some other vital part? IMHO, this spec shouldn't pass (to paraphrase Gandalf).
I'm using Rails 4.2.6, Rspec-Rails 3.4.2
Update
As Max pointed out, this is probably not at Rspec issue but instead something with Rails autoloading.
However i tried just typing
Backend::HomeController
In the Rails console, but there I get the expected error
NameError: uninitialized constant Backend::HomeController
And according to the Rails guide, both the console and the test suite autoloads. However I think I'm on the right track here.
I had this same problem before - you can read about the whole issue here:
Object.const_get and Rails - cutting off parent module names
but the meat of the answer comes from this answer from user Apneadiving:
Be aware that there are vicious cases in Rails development mode. In order to gain speed, the strict minimum is loaded. Then Rails looks for classes definitions when needed.
But this sometimes fails big time example, when you have say
::User
already loaded, and then look for::Admin::User
. Rails would not look for it, it will think::User
does the trick.This can be solved using
require_dependency
statements in your code.