0
votes

tl;dr: unable to rspec-test the devise controllers, help.

I am using Devise and have the following routes (default devise_for routes):

GET    /users/cancel(.:format)      devise/registrations#cancel
POST   /users(.:format)             devise/registrations#create
GET    /users/sign_up(.:format)     devise/registrations#new
GET    /users/edit(.:format)        devise/registrations#edit
PATCH  /users(.:format)             devise/registrations#update
PUT    /users(.:format)             devise/registrations#update
DELETE /users(.:format)             devise/registrations#destroy

I would like to test, using Rspec, that my controller method is spitting out the right output from a given set of parameters.

My spec file looks like this:

describe Users::RegistrationsController, type: 'controller' do
  it 'creates a user with given parameters' do

    post 'create', username: 'jonsnow', password: '012345678912345', authenticity_token: '12345'
    expect(response.status).to eq(200)
  end

end

The error I get is:

Failure/Error: post 'create', username: 'jonsnow', password: '012345678912345', authenticity_token: '12345'
ActionController::UrlGenerationError: 
No route matches {:action=>"create", :controller=>"users/registrations"}

It makes sense since I am using devise_for default routes and as you can see from the rake routes results, the correct route is devise/registrations#create, but I can't seem to find a way to specify the controller name to devise/registrations. I think it's 'inflected' from the controller class name or something to users/registrations. And I would preferably like to avoid messing with my routes in order to make my test successful. How can I accomplish that? (Please explain) Thanks in advance.

My gem versions:

rspec '3.2.1'
ruby '2.1.5'
rails '4.2.0'
1
Not sure Users::RegistrationsController is correct? maybe Devise?hlcfan
That's the name of the Devise::RegistrationsController subclass. If I am testing my controller subclass shouldn't it be named after it? I wouldn't be able to test my controller methods otherwise.JackyJohnson
most would argue you wouldn't test this as there literally thousands of tests in the devise gem already to make sure this works. github.com/plataformatec/devise/tree/master/test/controllersAnthony
you would do an integration test to make sure you can actually login using something like capybaraAnthony
@Anthony this doesn't help at all. everything i read online is either incomplete or points me away from this simple action. You're pointing out it may not be necessary to test it, but I don't understand how the developers insist on testing a controller independently to the route table but when testing for the controller response, which is what the controller is for in the first place, they force you to go back to routes but there's no way of explicitly saying which controller and action, everything seems to be inferred. Is it me or that's just bad design?JackyJohnson

1 Answers

-3
votes

There is some additional configuration required to be able to test controllers that inherit from Devise.

describe YourControllerWhichInheritsDevise, type: 'controller' do
  before do
    @request.env["devise.mapping"] = Devise.mappings[:user]
  end

  it 'creates a user with given parameters' do
    post 'create', username: 'jonsnow', password: '012345678912345', authenticity_token: '12345'
    expect(response.status).to eq(200)
  end
end

From the Devise README: "If you are testing Devise internal controllers or a controller that inherits from Devise's, you need to tell Devise which mapping should be used before a request. This is necessary because Devise gets this information from the router, but since functional tests do not pass through the router, it needs to be stated explicitly."