testcontainers

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 27, 2025 License: MIT Imports: 6 Imported by: 0

README


id: testcontainers

Testcontainers

Release Discord Test

A Testcontainers Service Implementation for Fiber.

:::note

Requires Go 1.23 and above

:::

Common Use Cases

  • Local development
  • Integration testing
  • Isolated service testing
  • End-to-end testing

Install

:::caution

This Service Implementation only supports Fiber v3.

:::

go get -u github.com/gofiber/fiber/v3
go get -u github.com/gofiber/contrib/testcontainers

Signature

NewModuleConfig

// NewModuleConfig creates a new container service config for a module.
//
// - The serviceKey is the key used to identify the service in the Fiber app's state.
// - The img is the image name to use for the container.
// - The run is the function to use to run the container. It's usually the Run function from the module, like [redis.Run] or [postgres.Run].
// - The opts are the functional options to pass to the run function. This argument is optional.
func NewModuleConfig[T testcontainers.Container](
 serviceKey string,
 img string,
 run func(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (T, error),
 opts ...testcontainers.ContainerCustomizer,
) Config[T] {

NewContainerConfig

// NewContainerConfig creates a new container service config for a generic container type,
// not created by a Testcontainers module. So this function best used in combination with
// the [AddService] function to add a custom container to the Fiber app's state.
//
// - The serviceKey is the key used to identify the service in the Fiber app's state.
// - The img is the image name to use for the container.
// - The opts are the functional options to pass to the [testcontainers.Run] function. This argument is optional.
//
// This function uses the [testcontainers.Run] function as the run function.
func NewContainerConfig[T *testcontainers.DockerContainer](serviceKey string, img string, opts ...testcontainers.ContainerCustomizer) Config[*testcontainers.DockerContainer]

AddService

// AddService adds a Testcontainers container as a [fiber.Service] for the Fiber app.
// It returns a pointer to a [ContainerService[T]] object, which contains the key used to identify
// the service in the Fiber app's state, and an error if the config is nil.
// The container should be a function like redis.Run or postgres.Run that returns a container type
// which embeds [testcontainers.Container].
// - The cfg is the Fiber app's configuration, needed to add the service to the Fiber app's state.
// - The containerConfig is the configuration for the container, where:
//   - The containerConfig.ServiceKey is the key used to identify the service in the Fiber app's state.
//   - The containerConfig.Run is the function to use to run the container. It's usually the Run function from the module, like redis.Run or postgres.Run.
//   - The containerConfig.Image is the image to use for the container.
//   - The containerConfig.Options are the functional options to pass to the [testcontainers.Run] function. This argument is optional.
//
// Use [NewModuleConfig] or [NewContainerConfig] helper functions to create valid containerConfig objects.
func AddService[T testcontainers.Container](cfg *fiber.Config, containerConfig Config[T]) (*ContainerService[T], error) {

Types

Config

The Config type is a generic type that is used to configure the container.

Property Type Description Default
ServiceKey string The key used to identify the service in the Fiber app's state. -
Image string The image name to use for the container. -
Run func(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (T, error) The function to use to run the container. It's usually the Run function from the testcontainers-go module, like redis.Run or postgres.Run -
Options []testcontainers.ContainerCustomizer The functional options to pass to the [testcontainers.Run] function. This argument is optional. -
// Config contains the configuration for a container service.
type Config[T testcontainers.Container] struct {
 // ServiceKey is the key used to identify the service in the Fiber app's state.
 ServiceKey string

 // Image is the image name to use for the container.
 Image string

 // Run is the function to use to run the container.
 // It's usually the Run function from the testcontainers-go module, like redis.Run or postgres.Run,
 // although it could be the generic [testcontainers.Run] function from the testcontainers-go package.
 Run func(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (T, error)

 // Options are the functional options to pass to the [testcontainers.Run] function. This argument is optional.
 // You can find the available options in the [testcontainers website].
 //
 // [testcontainers website]: https://golang.testcontainers.org/features/creating_container/#customizing-the-container
 Options []testcontainers.ContainerCustomizer
}

ContainerService

The ContainerService type is a generic type that embeds a testcontainers.Container interface, and implements the [fiber.Service] interface, thanks to the Start, String, State and Terminate methods. It manages the lifecycle of a testcontainers.Container instance, and it can be retrieved from the Fiber app's state calling the fiber.MustGetService function with the key returned by the ContainerService.Key method.

The type parameter T must implement the testcontainers.Container interface, as in the Testcontainers Go modules (e.g. redis.RedisContainer, postgres.PostgresContainer, etc.), or in the generic testcontainers.DockerContainer type, used for custom containers.

:::note

Since ContainerService implements the fiber.Service interface, container cleanup is handled automatically by the Fiber framework when the application shuts down. There's no need for manual cleanup code.

:::

type ContainerService[T testcontainers.Container] struct
Signature
 Key
// Key returns the key used to identify the service in the Fiber app's state.
// Consumers should use string constants for service keys to ensure consistency
// when retrieving services from the Fiber app's state.
func (c *ContainerService[T]) Key() string
Container
// Container returns the Testcontainers container instance, giving full access to the T type methods.
// It's useful to access the container's methods, like [testcontainers.Container.MappedPort]
// or [testcontainers.Container.Inspect].
func (c *ContainerService[T]) Container() T
Start
// Start creates and starts the container, calling the [run] function with the [img] and [opts] arguments.
// It implements the [fiber.Service] interface.
func (c *ContainerService[T]) Start(ctx context.Context) error
String
// String returns the service key, which uniquely identifies the container service.
// It implements the [fiber.Service] interface.
func (c *ContainerService[T]) String() string
State
// State returns the status of the container.
// It implements the [fiber.Service] interface.
func (c *ContainerService[T]) State(ctx context.Context) (string, error)
Terminate
// Terminate stops and removes the container. It implements the [fiber.Service] interface.
func (c *ContainerService[T]) Terminate(ctx context.Context) error

Common Errors

Error Description Resolution
ErrNilConfig Returned when the config is nil Ensure config is properly initialized
ErrContainerNotRunning Returned when the container is not running Check container state before operations
ErrEmptyServiceKey Returned when the service key is empty Provide a non-empty service key
ErrImageEmpty Returned when the image is empty Provide a valid image name
ErrRunNil Returned when the run is nil Provide a valid run function

Examples

You can find more examples in the testable examples.

Adding a module container using the Testcontainers Go's Redis module

package main

import (
 "fmt"
 "log"

 "github.com/gofiber/fiber/v3"

 "github.com/gofiber/contrib/testcontainers"
 tc "github.com/testcontainers/testcontainers-go"
 "github.com/testcontainers/testcontainers-go/modules/redis"
)

func main() {
 cfg := &fiber.Config{}

 // Define the base key for the module service.
 // The service returned by the [testcontainers.AddService] function,
 // using the [ContainerService.Key] method,
 // concatenates the base key with the "using testcontainers-go" suffix.
 const (
  redisKey    = "redis-module"
 )

 // Adding containers coming from the testcontainers-go modules,
 // in this case, a Redis and a Postgres container.

 redisModuleConfig := testcontainers.NewModuleConfig(redisKey, "redis:latest", redis.Run)
 redisSrv, err := testcontainers.AddService(cfg, redisModuleConfig)
 if err != nil {
  log.Println("error adding redis module:", err)
  return
 }

 // Create a new Fiber app, using the provided configuration.
 app := fiber.New(*cfg)

 // Retrieve all services from the app's state.
 // This returns a slice of all the services registered in the app's state.
 srvs := app.State().Services()

 // Retrieve the Redis container from the app's state using the key returned by the [ContainerService.Key] method.
 redisCtr := fiber.MustGetService[*testcontainers.ContainerService[*redis.RedisContainer]](app.State(), redisSrv.Key())

 // Start the Fiber app.
 app.Listen(":3000")
}

Adding a custom container using the Testcontainers Go package

package main

import (
 "fmt"
 "log"

 "github.com/gofiber/fiber/v3"

 "github.com/gofiber/contrib/testcontainers"
 tc "github.com/testcontainers/testcontainers-go"
)

func main() {
 cfg := &fiber.Config{}

 // Define the base key for the generic service.
 // The service returned by the [testcontainers.AddService] function,
 // using the [ContainerService.Key] method,
 // concatenates the base key with the "using testcontainers-go" suffix.
 const (
  nginxKey = "nginx-generic"
 )

 // Adding a generic container, directly from the testcontainers-go package.
 containerConfig := testcontainers.NewContainerConfig(nginxKey, "nginx:latest", tc.WithExposedPorts("80/tcp"))

 nginxSrv, err := testcontainers.AddService(cfg, containerConfig)
 if err != nil {
  log.Println("error adding nginx generic:", err)
  return
 }

 app := fiber.New(*cfg)

 nginxCtr := fiber.MustGetService[*testcontainers.ContainerService[*tc.DockerContainer]](app.State(), nginxSrv.Key())

 // Start the Fiber app.
 app.Listen(":3000")
}

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrNilConfig is returned when the config is nil.
	ErrNilConfig = errors.New("config is nil")

	// ErrContainerNotRunning is returned when the container is not running.
	ErrContainerNotRunning = errors.New("container is not running")

	// ErrEmptyServiceKey is returned when the service key is empty.
	ErrEmptyServiceKey = errors.New("service key is empty")

	// ErrImageEmpty is returned when the image is empty.
	ErrImageEmpty = errors.New("image is empty")

	// ErrRunNil is returned when the run is nil.
	ErrRunNil = errors.New("run is nil")
)

Functions

This section is empty.

Types

type Config

type Config[T tc.Container] struct {
	// ServiceKey is the key used to identify the service in the Fiber app's state.
	ServiceKey string

	// Image is the image name to use for the container.
	Image string

	// Run is the function to use to run the container.
	// It's usually the Run function from the testcontainers-go module, like redis.Run or postgres.Run,
	// although it could be the generic [tc.Run] function from the testcontainers-go package.
	Run func(ctx context.Context, img string, opts ...tc.ContainerCustomizer) (T, error)

	// Options are the functional options to pass to the [tc.Run] function. This argument is optional.
	// You can find the available options in the [testcontainers website].
	//
	// [testcontainers website]: https://golang.tc.org/features/creating_container/#customizing-the-container
	Options []tc.ContainerCustomizer
}

Config contains the configuration for a container service.

func NewContainerConfig

func NewContainerConfig(serviceKey string, img string, opts ...tc.ContainerCustomizer) Config[*tc.DockerContainer]

NewContainerConfig creates a new container service config for a generic container type, not created by a Testcontainers module. So this function best used in combination with the AddService function to add a custom container to the Fiber app's state.

- The serviceKey is the key used to identify the service in the Fiber app's state. - The img is the image name to use for the container. - The opts are the functional options to pass to the tc.Run function. This argument is optional.

This function uses the tc.Run function as the run function.

func NewModuleConfig

func NewModuleConfig[T tc.Container](
	serviceKey string,
	img string,
	run func(ctx context.Context, img string, opts ...tc.ContainerCustomizer) (T, error),
	opts ...tc.ContainerCustomizer,
) Config[T]

NewModuleConfig creates a new container service config for a module.

- The serviceKey is the key used to identify the service in the Fiber app's state. - The img is the image name to use for the container. - The run is the function to use to run the container. It's usually the Run function from the module, like [redis.Run] or [postgres.Run]. - The opts are the functional options to pass to the run function. This argument is optional.

type ContainerService

type ContainerService[T tc.Container] struct {
	// contains filtered or unexported fields
}

ContainerService represents a container that implements the fiber.Service interface. It manages the lifecycle of a tc.Container instance, and it can be retrieved from the Fiber app's state calling the fiber.MustGetService function with the key returned by the ContainerService.Key method.

The type parameter T must implement the tc.Container interface.

func AddService

func AddService[T tc.Container](cfg *fiber.Config, containerConfig Config[T]) (*ContainerService[T], error)

AddService adds a Testcontainers container as a fiber.Service for the Fiber app. It returns a pointer to a [ContainerService[T]] object, which contains the key used to identify the service in the Fiber app's state, and an error if the config is nil. The container should be a function like redis.Run or postgres.Run that returns a container type which embeds tc.Container. - The cfg is the Fiber app's configuration, needed to add the service to the Fiber app's state. - The containerConfig is the configuration for the container, where:

  • The containerConfig.ServiceKey is the key used to identify the service in the Fiber app's state.
  • The containerConfig.Run is the function to use to run the container. It's usually the Run function from the module, like redis.Run or postgres.Run.
  • The containerConfig.Image is the image to use for the container.
  • The containerConfig.Options are the functional options to pass to the tc.Run function. This argument is optional.

Use NewModuleConfig or NewContainerConfig helper functions to create valid containerConfig objects.

Example (FromContainer)
cfg := &fiber.Config{}

// Define the base key for the generic service.
// The service returned by the [testcontainers.AddService] function,
// using the [ContainerService.Key] method,
// concatenates the base key with the "using testcontainers-go" suffix.
const (
	nginxKey = "nginx-generic"
)

// Adding a generic container, directly from the testcontainers-go package.
containerConfig := testcontainers.NewContainerConfig(nginxKey, "nginx:latest", tc.WithExposedPorts("80/tcp"))

nginxSrv, err := testcontainers.AddService(cfg, containerConfig)
if err != nil {
	log.Println("error adding nginx generic:", err)
	return
}

app := fiber.New(*cfg)
fmt.Println(app.State().ServicesLen())

srvs := app.State().Services()
fmt.Println(len(srvs))

nginxCtr := fiber.MustGetService[*testcontainers.ContainerService[*tc.DockerContainer]](app.State(), nginxSrv.Key())

fmt.Println(nginxCtr.String())
Output:

1
1
nginx-generic (using testcontainers-go)
Example (FromModule)
cfg := &fiber.Config{}

// Define the base keys for the module services.
// The service returned by the [testcontainers.AddService] function,
// using the [ContainerService.Key] method,
// concatenates the base key with the "using testcontainers-go" suffix.
const (
	redisKey    = "redis-module"
	postgresKey = "postgres-module"
)

// Adding containers coming from the testcontainers-go modules,
// in this case, a Redis and a Postgres container.

redisModuleConfig := testcontainers.NewModuleConfig(redisKey, "redis:latest", redis.Run)
redisSrv, err := testcontainers.AddService(cfg, redisModuleConfig)
if err != nil {
	log.Println("error adding redis module:", err)
	return
}

postgresModuleConfig := testcontainers.NewModuleConfig(postgresKey, "postgres:latest", postgres.Run)
postgresSrv, err := testcontainers.AddService(cfg, postgresModuleConfig)
if err != nil {
	log.Println("error adding postgres module:", err)
	return
}

// Create a new Fiber app, using the provided configuration.
app := fiber.New(*cfg)

// Verify the number of services in the app's state.
fmt.Println(app.State().ServicesLen())

// Retrieve all services from the app's state.
// This returns a slice of all the services registered in the app's state.
srvs := app.State().Services()
fmt.Println(len(srvs))

// Retrieve the Redis container from the app's state using the key returned by the [ContainerService.Key] method.
redisCtr := fiber.MustGetService[*testcontainers.ContainerService[*redis.RedisContainer]](app.State(), redisSrv.Key())

// Retrieve the Postgres container from the app's state using the key returned by the [ContainerService.Key] method.
postgresCtr := fiber.MustGetService[*testcontainers.ContainerService[*postgres.PostgresContainer]](app.State(), postgresSrv.Key())

// Verify the string representation of the Redis and Postgres containers.
fmt.Println(redisCtr.String())
fmt.Println(postgresCtr.String())
Output:

2
2
redis-module (using testcontainers-go)
postgres-module (using testcontainers-go)

func (*ContainerService[T]) Container

func (c *ContainerService[T]) Container() T

Container returns the Testcontainers container instance, giving full access to the T type methods. It's useful to access the container's methods, like tc.Container.MappedPort or tc.Container.Inspect.

func (*ContainerService[T]) Key

func (c *ContainerService[T]) Key() string

Key returns the key used to identify the service in the Fiber app's state. Consumers should use string constants for service keys to ensure consistency when retrieving services from the Fiber app's state.

func (*ContainerService[T]) Start

func (c *ContainerService[T]) Start(ctx context.Context) error

Start creates and starts the container, calling the [run] function with the [img] and [opts] arguments. It implements the fiber.Service interface.

func (*ContainerService[T]) State

func (c *ContainerService[T]) State(ctx context.Context) (string, error)

State returns the status of the container. It implements the fiber.Service interface.

func (*ContainerService[T]) String

func (c *ContainerService[T]) String() string

String returns the service key, which uniquely identifies the container service. It implements the fiber.Service interface.

func (*ContainerService[T]) Terminate

func (c *ContainerService[T]) Terminate(ctx context.Context) error

Terminate stops and removes the container. It implements the fiber.Service interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL