Repository F# setup
open System
open System.IO
open System.Threading
open System.Threading.Tasks
open Axial
open Axial.Layers
open Axial.Console
open Axial.FileSystem
open Axial.Hosting
open Axial.Hosting.Browser
open Axial.Hosting.Node
open Axial.HttpClient
open Axial.PlatformService
open Axial.Process
open Axial.State
open Axial.Telemetry
open Axial.Telemetry.JavaScriptTesting And Layers
This page shows how the single IHttp.Send boundary makes HTTP workflows testable without a mocking library.
A Complete Fake In A Few Lines
The whole service surface is one method, and Response.create builds synthetic transcripts from an explicit timestamp:
type TestEnv =
{ Http: IHttp }
interface IHasHttp with
member this.Http = this.Http
let stub status body =
let startedAt = DateTimeOffset(2026, 1, 1, 0, 0, 0, TimeSpan.Zero)
{ Http =
{ new IHttp with
member _.Send(_, _) = async { return Ok(Response.create startedAt status body) } } }
[<Fact>]
let ``decodes the user payload`` () =
let env = stub 200 """{"id":1,"name":"Ada"}"""
let result = Http.getJson decodeUser "https://api.example.test/users/1" |> Flow.runSync env
test <@ result = Exit.Success { Id = 1; Name = "Ada" } @>The Live Service
Http.live adapts an explicit IClock and one HttpClient; Layer.succeed (Http.live …) exposes them as a layer:
type AppEnv =
{ Http: IHttp }
interface IHasHttp with
member this.Http = this.Http
let appLayer (clock: IClock) (client: HttpClient) : Layer<unit, Never, AppEnv> =
layer {
let! http = Layer.succeed (Http.live clock client)
return { Http = http }
}
workflow
|> Layer.provide (appLayer Clock.live client)
|> Flow.runSync ()Base addresses configured on the client work as usual — relative request URLs resolve against
client.BaseAddress:
let client = new HttpClient(BaseAddress = Uri "https://api.example.com/")
// Http.get "users/1" now resolves to https://api.example.com/users/1Service records compose the same way as the other platform packages:
type WorkerEnv =
{ HttpService: IHttp
ProcessService: IProcess }
interface IHasHttp with member this.Http = this.HttpService
interface IHasProcess with member this.Process = this.ProcessServicePortability
Request construction, the Request/Response modules, HttpError, and the DSL are portable and compile under
Fable. The Http.live service and Layer.succeed (Http.live …) are .NET-only: on other hosts, implement IHttp over the
platform's fetch primitive and provide it through the same environment record.
When Not To Fake
Fakes verify workflow logic, not server behavior. Keep a small number of tests against a real endpoint (a loopback listener works well) to cover the live service's encoding, header, timeout, and error mapping — the package's own test suite does exactly this.

