Sus::Fixtures::Async::HTTPGuidesGetting Started

Getting Started

This guide explains how to use the sus-fixtures-async-http gem to test HTTP clients and servers.

Installation

Add the gem to your project:

$ bundle add sus-fixtures-async-http

Usage

Here is a simple example showing how to test the default server:

include Sus::Fixtures::Async::HTTP::ServerContext

let(:response) {client.get("/")}

it 'can perform a request' do
	expect(response.read).to be == "Hello World!"
end

Custom Applications

You can create a custom application to test your own HTTP handlers:

include Sus::Fixtures::Async::HTTP::ServerContext

let(:app) do
	Protocol::HTTP::Middleware.for do |request|
		case request.path
		when "/"
			Protocol::HTTP::Response[200, {}, ["Home Page"]]
		when "/api/status"
			Protocol::HTTP::Response[200, {"content-type" => "application/json"}, ['{"status":"ok"}']]
		else
			Protocol::HTTP::Response[404, {}, ["Not Found"]]
		end
	end
end

it 'serves the home page' do
	response = client.get("/")
	expect(response.status).to be == 200
	expect(response.read).to be == "Home Page"
end

it 'serves API endpoints' do
	response = client.get("/api/status")
	expect(response.status).to be == 200
	expect(response.headers["content-type"]).to be == "application/json"
	expect(response.read).to be == '{"status":"ok"}'
end

it 'returns 404 for unknown paths' do
	response = client.get("/unknown")
	expect(response.status).to be == 404
end

Testing Different HTTP Methods

Test various HTTP methods and request bodies:

include Sus::Fixtures::Async::HTTP::ServerContext

let(:app) do
	Protocol::HTTP::Middleware.for do |request|
		case [request.method, request.path]
		when ["GET", "/users"]
			Protocol::HTTP::Response[200, {}, ['[{"id":1,"name":"John"}]']]
		when ["POST", "/users"]
			body = request.body.read
			Protocol::HTTP::Response[201, {}, ["Created: #{body}"]]
		when ["PUT", "/users/1"]
			body = request.body.read
			Protocol::HTTP::Response[200, {}, ["Updated: #{body}"]]
		when ["DELETE", "/users/1"]
			Protocol::HTTP::Response[204, {}, [""]]
		else
			Protocol::HTTP::Response[404, {}, ["Not Found"]]
		end
	end
end

it 'handles GET requests' do
	response = client.get("/users")
	expect(response.status).to be == 200
end

it 'handles POST requests' do
	response = client.post("/users", {}, ['{"name":"Alice"}'])
	expect(response.status).to be == 201
	expect(response.read).to be(:include?, "Alice")
end

it 'handles PUT requests' do
	response = client.put("/users/1", {}, ['{"name":"Bob"}'])
	expect(response.status).to be == 200
end

it 'handles DELETE requests' do
	response = client.delete("/users/1")
	expect(response.status).to be == 204
end

Configuration Options

Custom URLs and Ports

Override the server URL and endpoint options:

include Sus::Fixtures::Async::HTTP::ServerContext

let(:url) {"http://localhost:9999"}

let(:endpoint_options) do
	{reuse_port: true, protocol: protocol, timeout: 30}
end

it 'uses custom configuration' do
	expect(bound_url).to be(:include?, ":9999")
end

Protocol Selection

Test with different HTTP protocol versions:

include Sus::Fixtures::Async::HTTP::ServerContext

let(:protocol) {Async::HTTP::Protocol::HTTP2}

it 'uses HTTP/2 protocol' do
	response = client.get("/")
	expect(response).to have_attributes(version: "HTTP/2.0")
end