Skip to main content
Version: Next

Get started

Serverpod provides simple but feature rich test tools to make testing your backend a breeze.

warning

The test tools is an experimental feature. Experimental features should not be used in production environments, as their stability is uncertain and they may receive breaking changes in upcoming releases.

info

For Serverpod Mini projects, everything related to the database in this guide can be ignored.

Have an existing project? Follow these steps first!

For existing non-Mini projects, a few extra things need to be done:

  1. Add the server_test_tools_path key with the value test/integration/test_tools to config/generator.yaml:
server_test_tools_path: test/integration/test_tools

Without this key, the test tools file is not generated. With the above config the location of the test tools file is test/integration/test_tools/serverpod_test_tools.dart, but this can be set to any folder (though should be outside of lib as per Dart's test conventions).

  1. New projects now come with a test profile in docker-compose.yaml. This is not strictly mandatory, but is recommended to ensure that the testing state is never polluted. Add the snippet below to the docker-compose.yaml file in the server directory:
# Add to the existing services
postgres_test:
image: postgres:16.3
ports:
- '9090:5432'
environment:
POSTGRES_USER: postgres_test
POSTGRES_DB: <projectname>_test
POSTGRES_PASSWORD: "<insert database test password>"
volumes:
- <projectname>_test_data:/var/lib/postgresql/data
profiles:
- '' # Default profile
- test
redis_test:
image: redis:6.2.6
ports:
- '9091:6379'
command: redis-server --requirepass "<insert redis test password>"
environment:
- REDIS_REPLICATION_MODE=master
profiles:
- '' # Default profile
- test
volumes:
# ...
<projectname>_test_data:
Or copy the complete file here.

services:
# Development services
postgres:
image: postgres:16.3
ports:
- '8090:5432'
environment:
POSTGRES_USER: postgres
POSTGRES_DB: <projectname>
POSTGRES_PASSWORD: "<insert database development password>"
volumes:
- <projectname>_data:/var/lib/postgresql/data
profiles:
- '' # Default profile
- dev
redis:
image: redis:6.2.6
ports:
- '8091:6379'
command: redis-server --requirepass "<insert redis development password>"
environment:
- REDIS_REPLICATION_MODE=master
profiles:
- '' # Default profile
- dev

# Test services
postgres_test:
image: postgres:16.3
ports:
- '9090:5432'
environment:
POSTGRES_USER: postgres_test
POSTGRES_DB: <projectname>_test
POSTGRES_PASSWORD: "<insert database test password>"
volumes:
- <projectname>_test_data:/var/lib/postgresql/data
profiles:
- '' # Default profile
- test
redis_test:
image: redis:6.2.6
ports:
- '9091:6379'
command: redis-server --requirepass "<insert redis test password>"
environment:
- REDIS_REPLICATION_MODE=master
profiles:
- '' # Default profile
- test

volumes:
<projectname>_data:
<projectname>_test_data:

  1. Create a test.yaml file and add it to the config directory:
# This is the configuration file for your local test environment. All ports are set to zero in this file which makes the server find the next available port. This is needed to enable running tests concurrently.
# need to add the name of the database you are connecting to and the user name.
# The password for the database is stored in the config/passwords.yaml.


# Configuration for the main API test server.
apiServer:
port: 0
publicHost: localhost
publicPort: 0
publicScheme: http

# Configuration for the Insights test server.
insightsServer:
port: 0
publicHost: localhost
publicPort: 0
publicScheme: http

# Configuration for the web test server.
webServer:
port: 0
publicHost: localhost
publicPort: 0
publicScheme: http

# This is the database setup for your test server.
database:
host: localhost
port: 9090
name: <projectname>_test
user: postgres

# This is the setup for your Redis test instance.
redis:
enabled: false
host: localhost
port: 9091
  1. Add this entry to config/passwords.yaml
test:
database: '<insert database test password>'
redis: '<insert redis test password>'
  1. Add a dart_test.yaml file to the server directory (next to pubspec.yaml) with the following contents:
tags:
integration: {}

  1. Finally, add the test and serverpod_test packages as dev dependencies in pubspec.yaml:
dev_dependencies:
serverpod_test: <serverpod version> # Should be same version as the `serverpod` package
test: ^1.24.2

That's it, the project setup should be ready to start using the test tools!

Go to the server directory and generate the test tools:

serverpod generate --experimental-features testTools

The default location for the generated file is test/integration/test_tools/serverpod_test_tools.dart. The folder name test/integration is chosen to differentiate from unit tests (see the best practises section for more information on this).

The generated file exports a withServerpod helper that enables you to call your endpoints directly like regular functions:

import 'package:test/test.dart';

// Import the generated file, it contains everything you need.
import 'test_tools/serverpod_test_tools.dart';

void main() {
withServerpod('Given Example endpoint', (sessionBuilder, endpoints) {
test('when calling `hello` then should return greeting', () async {
final greeting = await endpoints.example.hello(sessionBuilder, 'Michael');
expect(greeting, 'Hello Michael');
});
});
}

A few things to note from the above example:

  • The test tools should be imported from the generated test tools file and not the serverpod_test package.
  • The withServerpod callback takes two parameters: sessionBuilder and endpoints.
    • sessionBuilder is used to build a session object that represents the server state during an endpoint call and is used to set up scenarios.
    • endpoints contains all your Serverpod endpoints and lets you call them.
tip

The location of the test tools can be changed by changing the server_test_tools_path key in config/generator.yaml. If you remove the server_test_tools_path key, the test tools will stop being generated.

Before the test can be run the Postgres and Redis also have to be started:

docker-compose up --build --detach

By default this starts up both the development and test profiles. To only start one profile, simply add --profile test to the command.

Now the test is ready to be run:

dart test

Happy testing!