logologo
Get Started
Guide
Development
Plugins
API
English
简体中文
Get Started
Guide
Development
Plugins
API
English
简体中文
logologo

Quick Start

Plugin Development Overview
Write Your First Plugin
Project Structure

Server Development

Overview
Plugin
Collections
Database
DataSourceManager
ResourceManager
ACL
Middleware
Cache
Event
Context
Migration
Logger
I18n
Command
CronJobManager
Test

Client Development

Overview
Plugin
Context
Router
ACL
DataSourceManager
Resource
Request
Styles & Themes
Logger
I18n
Test

Others

Plugin Upgrade Guide
Languages
Dependency Management
Build
Previous PageCronJobManager
Next PageOverview

#Test

NocoBase provides a complete set of testing tools to help developers quickly verify the correctness of database logic, API interfaces, and feature implementations during plugin development. This guide will introduce how to write, run, and organize these tests.

#Why Write Tests

Benefits of writing automated tests in plugin development:

  • Quickly verify database models, APIs, and business logic are correct
  • Avoid regression errors (automatically detect plugin compatibility after core upgrades)
  • Support continuous integration (CI) environments to automatically run tests
  • Support testing plugin functionality without starting the complete service

#Test Environment Basics

NocoBase provides two core testing tools:

ToolDescriptionPurpose
createMockDatabaseCreate in-memory database instanceTest database models and logic
createMockServerCreate complete application instance (includes database, plugins, APIs, etc.)Test business processes and interface behavior

#Using createMockDatabase for Database Testing

createMockDatabase is suitable for testing functionality directly related to databases, such as model definitions, field types, relationships, CRUD operations, etc.

#Basic Example

import { createMockDatabase, Database } from '@nocobase/database';

describe('Database test', () => {
  let db: Database;

  beforeEach(async () => {
    db = await createMockDatabase();
    await db.clean({ drop: true });
  });

  afterEach(async () => {
    await db.close();
  });

  it('should create and query data', async () => {
    const User = db.collection({
      name: 'users',
      fields: [
        { type: 'string', name: 'username' },
        { type: 'integer', name: 'age' },
      ],
    });

    await User.sync();

    const user = await db.getRepository('users').create({
      values: { username: 'testuser', age: 25 },
    });

    const found = await db.getRepository('users').findOne({
      filter: { username: 'testuser' },
    });

    expect(found.get('age')).toBe(25);
  });
});

#Testing CRUD Operations

const Posts = db.collection({
  name: 'posts',
  fields: [{ type: 'string', name: 'title' }],
});
await db.sync();

// Create
const post = await db.getRepository('posts').create({ values: { title: 'Initial Title' } });
expect(post.get('title')).toBe('Initial Title');

// Update
await db.getRepository('posts').update({
  filterByTk: post.get('id'),
  values: { title: 'Updated Title' },
});
const updated = await db.getRepository('posts').findOne({ filterByTk: post.get('id') });
expect(updated.get('title')).toBe('Updated Title');

#Testing Model Associations

const Users = db.collection({
  name: 'users',
  fields: [
    { type: 'string', name: 'username' },
    { type: 'hasMany', name: 'posts' },
  ],
});

const Posts = db.collection({
  name: 'posts',
  fields: [
    { type: 'string', name: 'title' },
    { type: 'belongsTo', name: 'author' },
  ],
});
await db.sync();

const user = await db.getRepository('users').create({ values: { username: 'tester' } });
await db.getRepository('posts').create({
  values: { title: 'Post 1', authorId: user.get('id') },
});

const result = await db.getRepository('users').findOne({
  filterByTk: user.get('id'),
  appends: ['posts'],
});
expect(result.get('posts')).toHaveLength(1);

#Using createMockServer for API Testing

createMockServer automatically creates a complete application instance including database, plugins, and API routes, making it ideal for testing plugin interfaces.

#Basic Example

import { createMockServer, MockServer } from '@nocobase/test';

describe('User API test', () => {
  let app: MockServer;

  beforeEach(async () => {
    app = await createMockServer({ plugins: ['users', 'auth'] });
  });

  afterEach(async () => {
    await app.destroy();
  });

  it('should create a user', async () => {
    const response = await app.agent()
      .post('/users:create')
      .send({ username: 'test', email: 'a@b.com', password: '123456' });

    expect(response.status).toBe(200);
    expect(response.body.username).toBe('test');
  });
});

#Testing API Queries and Updates

// Query user list
const list = await app.agent().get('/users:list');
expect(list.body.rows.length).toBeGreaterThan(0);

// Update user
const update = await app.agent().post(`/users:update/${id}`).send({ username: 'newname' });
expect(update.body.username).toBe('newname');

#Simulating Login Status or Permission Testing

You can enable the auth plugin when creating MockServer, then use the login interface to obtain token or session:

const res = await app
  .agent()
  .post('/auth:signin')
  .send({ 
    username: 'admin',
    password: 'admin123',
  });

const token = res.body.data.token;

await app
  .agent()
  .set('Authorization', `Bearer ${token}`)
  .get('/protected-endpoint');

You can also use the simpler login() method

await app.agent().login(userOrId);

#Organizing Test Files in Plugins

It's recommended to store server-side logic-related test files in the plugin's ./src/server/__tests__ folder.

packages/plugins/@my-project/plugin-hello/
├── src/                     # Source code directory
│   └── server/              # Server-side code
│       ├── __tests__/       # Test files directory
│       │   ├── db.test.ts   # Database related tests (using createMockDatabase)
│       │   └── api.test.ts  # API related tests

#Running Tests

# Specify directory
yarn test packages/plugins/@my-project/plugin-hello/src/server
# Specify file
yarn test packages/plugins/@my-project/plugin-hello/src/server/__tests__/db.test.ts