Set Cookie on Rack Mock Request
Rack apps are generally straightforward to test because of their very basic public interface. But where do we put specific things, in this case, a cookie for the request, on that env
argument it takes? Here's one way.
env
The env
argument that is sent to #call
in a Rack app is an variable that represents the environment of the request. It is a hash of CGI-like headers: request method, query params, http headers -- that sort of thing.
The HTTP_*
keys on the hash will be read as request headers from the environment.
Rack MockRequest Cookies
Rack provides a great little Rack::MockRequest
helper object in its library that will help us test our app. This object has a class method called env_for
which allows for quick construction of an env
var that is a request to a specified url.
On the returned env
we will continue to make modifications before passing it to our Rack app. We'll add our cookie header with a key of HTTP_COOKIE
. The value will be of the format cookieName=cookieValue
. We can handle multiple cookies by separating the cookies with ;
.
Let's say we're testing a token authentication middleware with rspec. Our spec may look something like this:
it "accepts an cookie token in the request" do
middleware = # ... instantiate rack middleware
env = Rack::MockRequest.env_for("/protected")
env["HTTP_COOKIE"] = "AUTH_COOKIE=123"
status, _, _ = middleware.call(env)
expect(status).to eq(200)
end
Then in our Rack app source, we can code for the availability of a cookie on the request. It might look like:
# ...
def call(env)
request = Rack::Request.new(env)
token = request.cookies["AUTH_TOKEN"]
# ...
end
Is this the easiest or best way to set cookies on requests when testing Rack apps? What do you do?