Async::HTTPGuidesTesting

Testing

This guide explains how to use Async::HTTP clients and servers in your tests.

In general, you should avoid making real HTTP requests in your tests. Instead, you should use a mock server or a fake client.

Mocking HTTP Responses

The mocking feature of Async::HTTP uses a real server running in a separate task, and routes all requests to it. This allows you to intercept requests and return custom responses, but still use the real HTTP client.

In order to enable this feature, you must create an instance of class Async::HTTP::Mock::Endpoint which will handle the requests.

require 'async/http'
require 'async/http/mock'

mock_endpoint = Async::HTTP::Mock::Endpoint.new

Sync do
	# Start a background server:
	server_task = Async(transient: true) do
		mock_endpoint.run do |request|
			# Respond to the request:
			::Protocol::HTTP::Response[200, {}, ["Hello, World"]]
		end
	end
	
	endpoint = Async::HTTP::Endpoint.parse("https://www.google.com")
	mocked_endpoint = mock_endpoint.wrap(endpoint)
	client = Async::HTTP::Client.new(mocked_endpoint)
	
	response = client.get("/")
	puts response.read
	# => "Hello, World"
end

Transparent Mocking

Using your test framework's mocking capabilities, you can easily replace the Async::HTTP::Client#new with a method that returns a client with a mocked endpoint.

Sus Integration

require 'async/http'
require 'async/http/mock'
require 'sus/fixtures/async/reactor_context'

include Sus::Fixtures::Async::ReactorContext

let(:mock_endpoint) {Async::HTTP::Mock::Endpoint.new}

def before
	super
	
	# Mock the HTTP client:
	mock(Async::HTTP::Client) do |mock|
		mock.wrap(:new) do |original, endpoint|
			original.call(mock_endpoint.wrap(endpoint))
		end
	end
	
	# Run the mock server:
	Async(transient: true) do
		mock_endpoint.run do |request|
			::Protocol::HTTP::Response[200, {}, ["Hello, World"]]
		end
	end
end

it "should perform a web request" do
	client = Async::HTTP::Client.new(Async::HTTP::Endpoint.parse("https://www.google.com"))
	response = client.get("/")
	# The response is mocked:
	expect(response.read).to be == "Hello, World"
end