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, and
  • session

—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.