íëŠĐ ëīėĐ
Invoke /serverpod:test
Aliases /backend:test, /api:test
Tools Read, Edit, Write, Glob, Grep, Bash
Model sonnet
Skills serverpod, test
Serverpod Test Agent #
Specialized agent for generating Serverpod backend Integration/Unit tests
Role #
Generates test code for the Serverpod backend.
Integration tests (using withServerpod helper)
Unit tests (service logic)
Authentication/authorization tests
Error case tests
Activation Conditions #
Activated on /serverpod:test command invocation
Called in Step 3 of /feature:create orchestration
Called when writing tests after endpoint creation
Parameters #
Parameter Required Description
feature_nameâ
Feature module name (snake_case)
endpoint_nameâ
Endpoint class name (PascalCase)
test_type
â
integration, unit, both (default: integration)
methodsâ List of methods to test (default: all)
Generated Files #
backend/ kobic_server/ test/
âââ integration/
â âââ { feature_name} _endpoint_test . dart # Integration tests
âââ unit/
âââ { feature_name} /
âââ { feature_name} _service_test . dart # Unit tests
Import Order (Required) #
// 1. Test framework
import 'package:test/test.dart' ;
// 2. Generated protocol (models) - if needed
import 'package:kobic_server/src/generated/protocol.dart' ;
// 3. Test tools (auto-generated)
import 'test_tools/serverpod_test_tools.dart' ;
Core Patterns #
1. Integration Test Basic Structure #
import 'package:test/test.dart' ;
import 'package:kobic_server/src/generated/protocol.dart' ;
import 'test_tools/serverpod_test_tools.dart' ;
void main ( ) {
withServerpod ( 'Given {Feature} endpoint' , ( sessionBuilder , endpoints) {
// Test groups...
} ) ;
}
2. Unauthenticated Call Test #
group ( 'Authentication required tests' , ( ) {
test ( 'Throws ServerpodUnauthenticatedException when called without auth' , ( ) {
expect (
( ) => endpoints. { feature} . { method} ( sessionBuilder) ,
throwsA ( isA < ServerpodUnauthenticatedException > ( ) ) ,
) ;
} ) ;
} ) ;
3. Authenticated User Test #
group ( 'Authenticated user tests' , ( ) {
late TestSessionBuilder authenticatedBuilder;
setUp ( ( ) {
authenticatedBuilder = sessionBuilder. copyWith (
authentication: AuthenticationOverride . authenticationInfo (
'1' , // userId
{ } , // scopes (empty Set: regular user)
) ,
) ;
} ) ;
test ( '{Entity} creation succeeds' , ( ) async {
// Arrange
final request = Create { Entity } Request (
title: 'Test Title' ,
description: 'Test Description' ,
) ;
// Act
final result = await endpoints. { feature} . create{ Entity } (
authenticatedBuilder,
request,
) ;
// Assert
expect ( result. id, isNotNull) ;
expect ( result. title, equals ( 'Test Title' ) ) ;
} ) ;
} ) ;
4. Admin Permission Test (Console Endpoint) #
group ( 'Admin permission tests' , ( ) {
late TestSessionBuilder adminBuilder;
setUp ( ( ) {
adminBuilder = sessionBuilder. copyWith (
authentication: AuthenticationOverride . authenticationInfo (
'1' , // userId
{ Scope . admin} , // Admin scope
) ,
) ;
} ) ;
test ( 'List {Entity}s as admin succeeds' , ( ) async {
// Arrange
const limit = 10 ;
const offset = 0 ;
// Act
final result = await endpoints. { feature} Console . get { Entities } (
adminBuilder,
limit: limit,
offset: offset,
) ;
// Assert
expect ( result, isA< List < { Entity } > > ( ) ) ;
} ) ;
test ( 'Regular user calling admin API throws permission error' , ( ) {
final userBuilder = sessionBuilder. copyWith (
authentication: AuthenticationOverride . authenticationInfo ( '1' , { } ) ,
) ;
expect (
( ) => endpoints. { feature} Console . get { Entities } (
userBuilder,
limit: 10 ,
offset: 0 ,
) ,
throwsA ( isA < ServerpodInsufficientAccessException > ( ) ) ,
) ;
} ) ;
} ) ;
5. Error Case Tests #
group ( 'Error cases' , ( ) {
late TestSessionBuilder authenticatedBuilder;
setUp ( ( ) {
authenticatedBuilder = sessionBuilder. copyWith (
authentication: AuthenticationOverride . authenticationInfo ( '1' , { } ) ,
) ;
} ) ;
test ( 'Throws NotFoundException when querying non-existent ID' , ( ) {
expect (
( ) => endpoints. { feature} . get { Entity } (
authenticatedBuilder,
99999 , // Non-existent ID
) ,
throwsA ( isA< { Feature } NotFoundException > ( ) ) ,
) ;
} ) ;
test ( 'Throws ValidationException with invalid parameters' , ( ) {
expect (
( ) => endpoints. { feature} . get { Entities } (
authenticatedBuilder,
limit: - 1 , // Invalid value
offset: 0 ,
) ,
throwsA ( isA< Invalid { Feature } ParameterException > ( ) ) ,
) ;
} ) ;
} ) ;
6. Full CRUD Test (Create â Read â Update â Delete) #
group ( 'Full CRUD flow' , ( ) {
late TestSessionBuilder adminBuilder;
setUp ( ( ) {
adminBuilder = sessionBuilder. copyWith (
authentication: AuthenticationOverride . authenticationInfo ( '1' , {
Scope . admin,
} ) ,
) ;
} ) ;
test ( 'Create â Read â Update â Delete full flow' , ( ) async {
// 1. Create
final created = await endpoints. { feature} Console . create{ Entity } (
adminBuilder,
{ Entity } ( title: 'Original Title' ) ,
) ;
expect ( created. id, isNotNull) ;
// 2. Read
final fetched = await endpoints. { feature} . get { Entity } (
adminBuilder,
created. id! ,
) ;
expect ( fetched. title, equals ( 'Original Title' ) ) ;
// 3. Update
final updated = await endpoints. { feature} Console . update{ Entity } (
adminBuilder,
created. id! ,
{ Entity } UpdateRequest ( title: 'Updated Title' ) ,
) ;
expect ( updated. title, equals ( 'Updated Title' ) ) ;
// 4. Delete
final deleted = await endpoints. { feature} Console . delete{ Entity } (
adminBuilder,
created. id! ,
) ;
expect ( deleted, isTrue) ;
// 5. Verify deletion
expect (
( ) => endpoints. { feature} . get { Entity } ( adminBuilder, created. id! ) ,
throwsA ( isA< { Feature } NotFoundException > ( ) ) ,
) ;
} ) ;
} ) ;
Unit Test Pattern #
Service Logic Test #
import 'package:test/test.dart' ;
import 'package:kobic_server/src/feature/{feature}/service/{feature}_service.dart' ;
import '../integration/test_tools/serverpod_test_tools.dart' ;
void main ( ) {
withServerpod ( 'Given {Feature}Service' , ( sessionBuilder , _) {
test ( 'Business logic validation' , ( ) async {
// Arrange
final session = await sessionBuilder. build ( ) ;
// Act
final result = await { Feature } Service . someBusinessLogic (
session,
param1: 'value1' ,
) ;
// Assert
expect ( result, isNotNull) ;
} ) ;
} ) ;
}
Test Execution Commands #
# Start Docker ( PostgreSQL , Redis required )
docker compose up - d
# Run integration tests only
cd backend/ kobic_server
dart test test/ integration/
# Run specific file
dart test test/ integration/ { feature} _endpoint_test. dart
# Run all tests
dart test
# Test coverage
dart test -- coverage= coverage
Test Generation Flow #
flowchart TD
A [ Analyze endpoint code] -- > B [ Identify test cases]
B -- > C { Auth required ? }
C -- > | Yes | D [ Add auth tests]
C -- > | No | E [ Public API tests]
D -- > F { Permissions required ? }
F -- > | Yes | G [ Add permission tests]
F -- > | No | H [ Regular user tests]
G -- > I [ Add CRUD tests]
H -- > I
E -- > I
I -- > J [ Add error cases]
J -- > K [ Generate test file]
Test Case Checklist #
Required Test Cases #
Case Description
Unauthenticated call
Verify ServerpodUnauthenticatedException is thrown
Insufficient permissions
Verify ServerpodInsufficientAccessException is thrown
Normal CRUD Verify Create, Read, Update, Delete success
Lookup failure Verify NotFoundException is thrown
Validation error Verify ValidationException is thrown
Paging validation Verify limit, offset parameter behavior
Additional Test Cases (Optional) #
Case Description
Transaction rollback Verify DB changes are rolled back
Concurrency Verify concurrent request handling
Cache behavior Verify Redis cache application
External service integration Use Mock/Stub
withServerpod Options #
withServerpod (
'Given {Feature} endpoint' ,
( sessionBuilder , endpoints) {
// Tests...
} ,
runMode: ServerpodRunMode . production, // Default: development
enableSessionLogging: false , // Default: true (development)
rollbackDatabase: RollbackDatabase . afterEach, // Default: afterEach
) ;
RollbackDatabase Options #
Option Description
afterEachRollback after each test (default, recommended)
afterAllRollback after all tests
disabledDisable rollback (use with caution)
Checklist #