Reputation: 3294
I'm implementing an API on my app, and testing it with Rspec.
my items controller doesn't have the new
or edit
actions, and the routes.rb has no routes for them:
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :items, except: [:new, :edit]
end
end
My rspec test for them looks like:
it "raises error on #new" do
expect(:get => "/api/v1/items/new").to have_http_status(404)
end
but when I execute the tests on it I get:
Api::V1::ItemsController routing raises error on #new
Failure/Error: expect(:get => "/api/v1/items/new").to have_http_status(404)
expected a response object, but an instance of Hash was received
# ./spec/routing/items_routing_spec.rb:11:in `block (3 levels) in <top (required)>'
I'm not sure how to deal with this case and get the test to pass.
Upvotes: 1
Views: 1429
Reputation: 15791
You are probably looking for be_routable
matcher:
it { expect(get: '/api/v1/items/new').to_not be_routable }
From docs:
The be_routable matcher is best used with should_not to specify that a given route should not be routable. It is available in routing specs (in spec/routing) and controller specs (in spec/controllers).
As a workaround for the issue with new
being interpreted as show
, you can use alternative matcher called route_to
:
it { expect(get: '/api/v1/items/new').to_not route_to('/api/v1/items#new') }
or
it { expect(get: '/api/v1/items/new').to_not route_to(controller: '/api/v1/items', action: 'new') }
Upvotes: 4
Reputation: 4982
You're passing in a hash to expect:
{ :get => "/api/v1/items/new" }
but your assertion is only valid for response objects. You probably want to do something along the lines of
get "/api/v1/items/new"
expect(response).to have_http_status(404)
but if you haven't defined that route yet, this test will probably fail as well.
See this for documentation on the have_http_status matcher.
Upvotes: 2