What a request spec actually is

Free preview 3 min to read

The layer the previous course left for later

The course right before this one, System testing: Capybara, spent seven lessons on type: :system: a browser, JavaScript and Capybara's DSL. It closed by naming the layer underneath: this app's spec/requests/, dozens of files and a few hundred examples that already prove server-side correctness without a browser. This course covers that layer in depth.

The syntax: type: :request

The request specs in this app open the same way. From spec/requests/auth_spec.rb:

require 'rails_helper'

RSpec.describe "Authentication", type: :request do
  let(:user) { create(:user) }

  describe "Sessions" do
    describe "GET /auth/sign-in" do
      it "renders the sign in page" do
        get auth_sign_in_path
        expect(response).to have_http_status(:success)
      end
    end
  end
end

type: :request is the RSpec metadata tag, and this app's spec/rails_helper.rb describes it in a comment: "RSpec Rails uses metadata to mix in different behaviours to your tests, for example enabling you to call get and post in request specs." Declaring it is what makes get, auth_sign_in_path and response exist inside the example. The one file under spec/requests/ without the tag, client_ip_spec.rb, doesn't make requests at all: it builds a Rack environment by hand and calls ActionDispatch::RemoteIp directly.

The HTTP-verb helpers this app's specs call

A grep across spec/requests/ finds get most often, then post, patch and delete. put doesn't appear once: every update in this app's specs goes through patch, matching Rails' convention for partial updates. Each of those is a method provided by the type: :request machinery. It sends an HTTP-shaped request (verb, path, params) into the full running application and gets a response back.

A full round trip, not a shortcut

A request spec's get, post, patch or delete doesn't call a controller action directly, and it doesn't stub anything by default. It goes in through Rails' router and the middleware stack: session handling, CSRF, this app's rack-attack gem and everything else config/application.rb wires up. Then it reaches the controller action, runs its before_actions and the view or JSON renderer, and comes back out as a response object. That's the same round trip an HTTP client makes, minus a TCP socket and a browser. It's also the difference from the previous course's system specs: no rendering engine, no JavaScript and no DOM, only the server-side path from start to finish.

What this course covers

Seven lessons. This one covers type: :request and the verbs this app uses. Lesson 2 covers the assertions this app's specs make on a response: have_http_status, response.body and the less common response.status. Lesson 3 separates a request spec from the previous course's system spec and from the older controller-spec style, including why the Rails and RSpec teams now steer away from that last one. Lesson 4 quotes this app's reusable sign_in helper. Lesson 5 walks through CRUD and JSON examples from this app's admin and execution specs. Lesson 6 covers testing what should not happen: access control and failure paths. Lesson 7 puts it together, with a small challenge and a pointer to the next course.

Lesson 1 of 7 · free

Keep going with lesson 2

The response assertions this app's specs make

Covers have_http_status, response.body and response.status, and notes that this app parses JSON by hand instead of using parsed_body.

A free account also gives you the quizzes, your progress and notes, and the discussion.

Type to start searching...