This section of the documentation is still work in progress and soon will be updated with more examples and details.
Please be patient while we work on the ongoing users and profiles refactoring as part of issue #376 .

Pocketbase exposes several test mocks and stubs (eg. tests.TestApp, tests.ApiScenario, tests.MockMultipartData, etc.) to help you write unit and integration tests for your app.

You could find more information in the github.com/pocketbase/pocketbase/tests sub package, but here are some examples:

Let's say that we've added a new API route /api/hello to our application:

// main_test.go package main import ( "log" "net/http" "github.com/labstack/echo/v5" "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/apis" "github.com/pocketbase/pocketbase/core" ) func bindAppHooks(app core.App) { app.OnBeforeServe().Add(func(e *core.ServeEvent) error { e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/my/hello", Handler: func(c echo.Context) error { return c.String(200, "Hello world!") }, Middlewares: []echo.MiddlewareFunc{ apis.RequireAdminAuth(), }, }) return nil }) } func main() { app := pocketbase.New() bindAppHooks(app) if err := app.Start(); err != nil { log.Fatal(err) } }

To test the above endpoint, we want to:

  • ensure it handles only GET requests
  • ensure that it can be accessed only by admins
  • check if the response body is properly set

Here is a simple integration test for the above test cases:

// main_test.go package main import ( "net/http" "testing" "github.com/pocketbase/pocketbase/tests" ) func TestHelloEndpoint(t *testing.T) { // setup the test app instance setupTestApp := func() (*tests.TestApp, error) { app, err := tests.NewTestApp() if err != nil { return nil, err } bindAppHooks(app) return app, nil } scenarios := []tests.ApiScenario{ { Name: "try with different http method, eg. POST", Method: http.MethodPost, Url: "/my/hello", ExpectedStatus: 405, ExpectedContent: []string{""data":{}"}, TestAppFactory: setupTestApp, }, { Name: "try as guest (aka. no Authorization header)", Method: http.MethodGet, Url: "/my/hello", ExpectedStatus: 401, ExpectedContent: []string{""data":{}"}, TestAppFactory: setupTestApp, }, { Name: "try as authenticated user", Method: http.MethodGet, Url: "/my/hello", RequestHeaders: map[string]string{ // using a valid auth token for a user from the test database "Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic", }, ExpectedStatus: 401, ExpectedContent: []string{""data":{}"}, TestAppFactory: setupTestApp, }, { Name: "try as authenticated admin", Method: http.MethodGet, Url: "/my/hello", RequestHeaders: map[string]string{ // using a valid auth token for an admin from the test database "Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo", }, ExpectedStatus: 200, ExpectedContent: []string{"Hello world!"}, TestAppFactory: setupTestApp, }, } for _, scenario := range scenarios { scenario.Test(t) } }