Testing

Okapi provides comprehensive testing utilities through the okapitest package to help you write robust tests for your handlers and middleware.

Quick Start

import (
    "testing"
    "github.com/jkaninda/okapi"
    "github.com/jkaninda/okapi/okapitest"
)

func TestGetBooksHandler(t *testing.T) {
    // Create a test server
    server := okapi.NewTestServer(t)
    server.Get("/books", GetBooksHandler)
    
    // Make request and assert response
    okapitest.GET(t, server.BaseURL+"/books").
        ExpectStatusOK().
        ExpectBodyContains("The Go Programming Language")
}

Testing Approaches

The test client provides a fluent API for making multiple requests with shared configuration:

func TestBooksAPI(t *testing.T) {
    // Setup test server
    server := okapi.NewTestServer(t)
    server.Get("/books", GetBooksHandler)
    server.Get("/books/:id", GetBookHandler)
    server.Post("/books", CreateBookHandler)
    
    // Create reusable client
    client := okapitest.NewClient(t, server.BaseURL)
    
    // Test listing books
    client.GET("/books").
        ExpectStatusOK().
        ExpectBodyContains("The Go Programming Language").
        ExpectHeader("X-Version", "1.0.0")

    // Test getting a specific book
    client.GET("/books/1").
        ExpectStatusOK().
        ExpectBodyContains("The Go Programming Language")
    
    // Test book not found
    client.GET("/books/999").
        ExpectStatusNotFound().
        ExpectBodyContains("Book not found")
    
    // Test creating a book
    newBook := Book{
        ID:    6,
        Name:  "Sample Book",
        Price: 20,
        Year:  2024,
        Qty:   5,
    }
    client.POST("/books").
        JSONBody(newBook).
        ExpectStatusCreated().
        ExpectBodyContains("Sample Book")
}

2. Using Standalone Request Helpers

For simpler test cases or one-off requests:

func TestGetBookHandler(t *testing.T) {
    server := okapi.NewTestServer(t)
    server.Get("/books/:id", GetBookHandler)
    
    // Test successful retrieval
    okapitest.GET(t, server.BaseURL+"/books/1").
        ExpectStatusOK().
        ExpectBodyContains("The Go Programming Language")
    
    // Test not found scenario
    okapitest.GET(t, server.BaseURL+"/books/999").
        ExpectStatusNotFound().
        ExpectBodyContains("Book not found")
}

func TestCreateBookHandler(t *testing.T) {
    server := okapi.NewTestServer(t)
    server.Post("/books", CreateBookHandler)
    
    book := Book{
        ID:    6,
        Name:  "Sample Book",
        Price: 20,
        Year:  2024,
        Qty:   5,
    }
    
    okapitest.POST(t, server.BaseURL+"/books").
        JSONBody(book).
        ExpectStatusCreated().
        ExpectBodyContains("Sample Book")
}

Available Assertions

The test utilities support various assertions:

// Status code assertions
.ExpectStatusOK()           // 200
.ExpectStatusCreated()      // 201
.ExpectStatusNotFound()     // 404
.ExpectStatus(code int)     // Custom status code

// Body assertions
.ExpectBodyContains(text string)
.ExpectBodyEquals(text string)
.ExpectJSONBody(expected interface{})

// Header assertions
.ExpectHeader(key, value string)

Testing with Custom Headers

func TestAuthenticatedRequest(t *testing.T) {
    server := okapi.NewTestServer(t)
    server.Get("/protected", ProtectedHandler)
    
    client := okapitest.NewClient(t, server.BaseURL)
    
    client.GET("/protected").
        Header("Authorization", "Bearer token123").
        ExpectStatusOK()
}

Testing Middleware

func TestAuthMiddleware(t *testing.T) {
    server := okapi.NewTestServer(t)
    server.Use(AuthMiddleware)
    server.Get("/protected", ProtectedHandler)
    
    client := okapitest.NewClient(t, server.BaseURL)
    
    // Test without auth - should fail
    client.GET("/protected").
        ExpectStatus(401)
    
    // Test with auth - should succeed
    client.GET("/protected").
        Header("Authorization", "Bearer valid-token").
        ExpectStatusOK()
}