Testing Guide
This guide explains how to write unit and integration tests for applications using TableTheory.
Quick Links (by SDK)
- Go: this document (mocks in
pkg/mocks) - TypeScript: runtime-specific testing guide is staged alongside this document in the shared TableTheory subtree
- Python: runtime-specific testing guide is staged alongside this document in the shared TableTheory subtree
Unit Testing with Mocks
To write unit tests without connecting to DynamoDB, use the core.DB interface and the provided mocks.
1. Define Dependencies via Interface
Don’t depend on the concrete *tabletheory.DB struct. Use core.DB.
import "github.com/theory-cloud/tabletheory/pkg/core"
type UserService struct {
db core.DB
}
func NewUserService(db core.DB) *UserService {
return &UserService{db: db}
}
2. Use Mocks in Tests
TableTheory provides mocks in the mocks package (or generate your own with mockery).
import (
"testing"
"github.com/stretchr/testify/mock"
"github.com/theory-cloud/tabletheory/pkg/mocks"
)
func TestCreateUser(t *testing.T) {
// Setup Mocks
mockDB := new(mocks.MockDB)
mockQuery := new(mocks.MockQuery)
// Expect Model() to be called, return mock query
mockDB.On("Model", mock.Anything).Return(mockQuery)
// Expect Create() to be called
mockQuery.On("Create").Return(nil)
// Test Service
service := NewUserService(mockDB)
err := service.CreateUser("john")
// Assertions
if err != nil {
t.Errorf("Expected no error, got %v", err)
}
mockDB.AssertExpectations(t)
}
3. Encryption + lifecycle determinism (Go)
If you use theorydb:"encrypted" fields or lifecycle tags, inject test doubles via session.Config:
import (
"bytes"
"testing"
"time"
"github.com/aws/aws-sdk-go-v2/service/kms"
"github.com/theory-cloud/tabletheory"
"github.com/theory-cloud/tabletheory/pkg/mocks"
"github.com/theory-cloud/tabletheory/pkg/session"
"github.com/stretchr/testify/mock"
)
func TestEncryptedWrites(t *testing.T) {
kmsMock := new(mocks.MockKMSClient)
kmsMock.On("GenerateDataKey", mock.Anything, mock.Anything, mock.Anything).
Return(&kms.GenerateDataKeyOutput{
Plaintext: bytes.Repeat([]byte{0x00}, 32),
CiphertextBlob: []byte("edk"),
}, nil)
db, _ := tabletheory.New(session.Config{
Region: "us-east-1",
KMSKeyARN: "arn:aws:kms:us-east-1:111111111111:key/test",
KMSClient: kmsMock,
EncryptionRand: bytes.NewReader(bytes.Repeat([]byte{0x01}, 64)),
Now: func() time.Time { return time.Unix(0, 0).UTC() },
})
_ = db
}
TypeScript unit testing
Use @theory-cloud/tabletheory-ts/testkit for a strict AWS SDK v3 send() mock and deterministic helpers:
import { PutItemCommand } from "@aws-sdk/client-dynamodb";
import { TheorydbClient } from "@theory-cloud/tabletheory-ts";
import {
createMockDynamoDBClient,
fixedNow,
} from "@theory-cloud/tabletheory-ts/testkit";
const mock = createMockDynamoDBClient();
mock.when(PutItemCommand, async () => ({}));
const db = new TheorydbClient(mock.client, {
now: fixedNow("2026-01-16T00:00:00.000000000Z"),
});
Python unit testing
Use theorydb_py.mocks for strict fakes and deterministic encryption nonces:
from theorydb_py import Table
from theorydb_py.mocks import FakeDynamoDBClient, FakeKmsClient
fake_ddb = FakeDynamoDBClient()
fake_kms = FakeKmsClient(plaintext_key=b"\x00" * 32, ciphertext_blob=b"edk")
table = Table(model, client=fake_ddb, kms_key_arn="arn:aws:kms:...", kms_client=fake_kms, rand_bytes=lambda n: b"\x01" * n)
Integration Testing
For integration tests, connect to a real DynamoDB instance or DynamoDB Local.
TypeScript integration tests
make docker-up
npm --prefix ts run test:integration
Python integration tests
make docker-up
uv --directory py run pytest -q tests/integration
Go integration tests
func TestIntegration(t *testing.T) {
// Connect to DynamoDB Local
db, _ := tabletheory.New(session.Config{
Endpoint: "http://localhost:8000",
Region: "us-east-1",
})
// Create Table
db.CreateTable(&User{})
// Run Test
err := db.Model(&User{ID: "1"}).Create()
if err != nil {
t.Fatal(err)
}
}