What to Expect in a Request Spec
Learn about requests and behavior testing in requests spec, hash variables, HTTP response codes verification, and controller redirection.
Behavior testing
Our main goal in a request spec is to test behavior. We find that test-double validations work well here. If we’re interested in testing the final state after the request, in addition to testing the changes to the database, there are a few other substantive things we can test.
response
variable access
After the request has been made, we have access to a response
variable. Since request specs wrap Rails integration tests, RSpec does render the view, though if we are testing view behavior, we recommend using system specs, where we have access to the Capybara matchers and not just the Rails integration spec matchers as described in Minitest.
Hash variables
After the request has been made, we have access to three special hash variables that we can test—
cookies
,flash
, andsession
—all of which test the values the Rails process stored in those buckets.
RSpec provides the response.status
value and there is, at least in theory, a have_http_matcher
, which allows us to compare against logical values like :success
and :error
.
Let’s talk about these three types of assertions in more detail.
HTTP response codes verification
We can use have_http_status
to verify the HTTP response code sent back to the browser from Rails. Normally we’d use this assertion to ensure that our controller correctly distinguishes between success and redirect or error cases.
The value passed to have_http_status
is usually one of four special symbols:
Symbol | HTTP Code Equivalent |
---|---|
:success |
200–299 |
:redirect |
300–399 |
:missing |
404 |
:error |
500–599 |
If we need to test for a more specific response, we can pass either the exact HTTP code number or one of the associated symbols defined by Rack. Note that RSpec uses the codes defined by SYMBOL_TO_STATUS_CODE
. The most common case we’ve had for specific HTTP codes is the need to distinguish between 301 permanent redirects (:moved-permanently
) and other redirects.
Controllers redirection
When we expect the controller to redirect, we can use the redirect_to
matcher to assert the exact nature of the redirect. The argument to redirect_to
is pretty much anything Rails can convert to a URL, although the method’s behavior is slightly different based on what the argument actually is. The code for redirect_to
explicitly includes have_http_status(:redirect)
, so we don’t need to duplicate that assertion.
URLs testing redirects in request tests
If the argument to redirect_to
is the name of a URL because it’s a string or a method for a Rails named route, or because it’s an object that has a Rails RESTful route, then the assertion passes if and only if the redirecting URL exactly matches the asserted URL. For testing purposes, Rails will assume that the application’s local hostname is http://www.example.com
. If that’s too exact a test for our taste, we can pass a hash to redirect_to
, which specifies the :controller
, :action
, and any parameters. If the argument is a hash, then assert_redirected_to
checks only the exact key/value pairs in the hash; other parts of the URL are not checked.
Redirects validations
Request and controller tests do not—repeat, do not—follow the redirect. Any data validation tests we write apply only to the method before the redirect occurs. If we need our test to follow the redirection for some reason, we’re cordially invited to try a system test; see Integration Testing with Capybara and Cucumber.
Get hands-on with 1400+ tech skills courses.