Huma provides a number of helpers for testing your API. The most important is the humatest package, which allows you to run a test server and make requests against it.
packagemainimport("context""fmt""net/http""github.com/danielgtaylor/huma/v2""github.com/danielgtaylor/huma/v2/adapters/humachi""github.com/danielgtaylor/huma/v2/humacli""github.com/go-chi/chi/v5"_"github.com/danielgtaylor/huma/v2/formats/cbor")// Options for the CLI.typeOptionsstruct{Portint`help:"Port to listen on" short:"p" default:"8888"`}// GreetingOutput represents the greeting operation response.typeGreetingOutputstruct{Bodystruct{Messagestring`json:"message" example:"Hello, world!" doc:"Greeting message"`}}// ReviewInput represents the review operation request.typeReviewInputstruct{Bodystruct{Authorstring`json:"author" maxLength:"10" doc:"Author of the review"`Ratingint`json:"rating" minimum:"1" maximum:"5" doc:"Rating from 1 to 5"`Messagestring`json:"message,omitempty" maxLength:"100" doc:"Review message"`}}funcaddRoutes(apihuma.API){// Register GET /greeting/{name}huma.Register(api,huma.Operation{OperationID:"get-greeting",Method:http.MethodGet,Path:"/greeting/{name}",Summary:"Get a greeting",Description:"Get a greeting for a person by name.",Tags:[]string{"Greetings"},},func(ctxcontext.Context,input*struct{Namestring`path:"name" maxLength:"30" example:"world" doc:"Name to greet"`})(*GreetingOutput,error){resp:=&GreetingOutput{}resp.Body.Message=fmt.Sprintf("Hello, %s!",input.Name)returnresp,nil})// Register POST /reviewshuma.Register(api,huma.Operation{OperationID:"post-review",Method:http.MethodPost,Path:"/reviews",Summary:"Post a review",Tags:[]string{"Reviews"},DefaultStatus:http.StatusCreated,},func(ctxcontext.Context,i*ReviewInput)(*struct{},error){// TODO: save review in data store.returnnil,nil})}funcmain(){// Create a CLI app which takes a port option.cli:=humacli.New(func(hookshumacli.Hooks,options*Options){// Create a new router & APIrouter:=chi.NewMux()api:=humachi.New(router,huma.DefaultConfig("My API","1.0.0"))addRoutes(api)// Tell the CLI how to start your server.hooks.OnStart(func(){fmt.Printf("Starting server on port %d...\n",options.Port)http.ListenAndServe(fmt.Sprintf(":%d",options.Port),router)})})// Run the CLI. When passed no commands, it starts the server.cli.Run()}
Use the humatest package to create a test API and then register your routes against it. Next, make get or post requests against it to test the various user scenarios you have to support:
packagemainimport("strings""testing""github.com/danielgtaylor/huma/v2/humatest")funcTestGetGreeting(t*testing.T){_,api:=humatest.New(t)addRoutes(api)resp:=api.Get("/greeting/world")if!strings.Contains(resp.Body.String(),"Hello, world!"){t.Fatalf("Unexpected response: %s",resp.Body.String())}}funcTestPutReview(t*testing.T){_,api:=humatest.New(t)addRoutes(api)resp:=api.Post("/reviews",map[string]any{"author":"daniel","rating":5,})ifresp.Code!=201{t.Fatalf("Unexpected status code: %d",resp.Code)}}funcTestPutReviewError(t*testing.T){_,api:=humatest.New(t)addRoutes(api)resp:=api.Post("/reviews",map[string]any{"rating":10,})ifresp.Code!=422{t.Fatalf("Unexpected status code: %d",resp.Code)}}
Now you can run your tests!
Terminal
$gotest-cover
You may also need to send requests with a custom context.Context. For example, you may need to test an authenticated route, or test using some other request-specific values.
funcTestGetGreeting(t*testing.T){_,api:=humatest.New(t)addRoutes(api)ctx:=context.Background()// define your necessary contextresp:=api.GetCtx(ctx,"/greeting/world")// provide it using the 'Ctx' suffixed methodsif!strings.Contains(resp.Body.String(),"Hello, world!"){t.Fatalf("Unexpected response: %s",resp.Body.String())}}