fontcolor_theme
Deepkit Framework

测试

Deepkit 框架中的服务和控制器旨在支持 SOLID 和简洁的代码,具有良好的设计、封装和分离。这些特性使代码易于测试。

本文档将向你展示如何使用 ts-jest 设置名为 Jest 的测试框架。为此,运行以下命令安装 jestts-jest

npm install jest ts-jest @types/jest

Jest 需要一些配置选项来知道从哪里查找测试套件以及如何编译 TS 代码。将以下配置添加到你的 package.json

{
  ...,

  "jest": {
    "transform": {
      "^.+\\.(ts|tsx)$": "ts-jest"
    },
    "testEnvironment": "node",
    "testMatch": [
      "**/*.spec.ts"
    ]
  }
}

你的测试文件应命名为 .spec.ts。创建一个 test.spec.ts 文件,并写入以下内容。

test('first test', () => {
    expect(1 + 1).toBe(2);
});

现在你可以使用 jest 命令一次性运行所有测试套件。

$ node_modules/.bin/jest
 PASS  ./test.spec.ts
  ✓ first test (1 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.23 s, estimated 1 s
Ran all test suites.

请阅读 Jest-Dokumentation 以了解更多关于 Jest CLI 工具的工作方式,以及如何编写更复杂的测试和完整的测试套件。

单元测试

在可能的情况下,你应该为你的服务编写单元测试。你的服务依赖越简单、分离越好、定义越清晰,就越容易对其进行测试。在这种情况下,你可以编写如下简单测试:

export class MyService {
    helloWorld() {
        return 'hello world';
    }
}
//
import { MyService } from './my-service.ts';

test('hello world', () => {
    const myService = new MyService();
    expect(myService.helloWorld()).toBe('hello world');
});

集成测试

并非总是可以编写单元测试,也并非总是用单元测试覆盖业务关键代码和行为的最高效方式。特别是当你的架构非常复杂时,能够轻松地执行端到端的集成测试将非常有益。

正如你在依赖注入章节中已经了解到的那样,依赖注入容器是 Deepkit 的核心。所有服务都在这里构建并运行。你的应用定义了服务(providers)、控制器、监听器和 imports。对于集成测试,你不一定希望在一个测试用例中拥有所有服务,但通常希望有一个精简版的应用来测试关键区域。

import { createTestingApp } from '@deepkit/framework';
import { http, HttpRequest } from '@deepkit/http';

test('http controller', async () => {
    class MyController {

        @http.GET()
        hello(@http.query() text: string) {
            return 'hello ' + text;
        }
    }

    const testing = createTestingApp({ controllers: [MyController] });
    await testing.startServer();

    const response = await testing.request(HttpRequest.GET('/').query({text: 'world'}));

    expect(response.getHeader('content-type')).toBe('text/plain; charset=utf-8');
    expect(response.body.toString()).toBe('hello world');
});
import { createTestingApp } from '@deepkit/framework';

test('service', async () => {
    class MyService {
        helloWorld() {
            return 'hello world';
        }
    }

    const testing = createTestingApp({ providers: [MyService] });

    // 访问依赖注入容器并实例化 MyService
    const myService = testing.app.get(MyService);

    expect(myService.helloWorld()).toBe('hello world');
});

如果你已将应用拆分为多个模块,你可以更轻松地测试它们。例如,假设你创建了一个 AppCoreModule 并希望测试一些服务。

class Config {
    items: number = 10;
}

export class MyService {
    constructor(protected items: Config['items']) {

    }

    doIt(): boolean {
        // 做点什么
        return true;
    }
}

export AppCoreModule = new AppModule({}, {
    config: config,
    provides: [MyService]
}, 'core');

你可以如下使用你的模块:

import { AppCoreModule } from './app-core.ts';

new App({
    imports: [new AppCoreModule]
}).run();

并且在不启动整个应用服务器的情况下测试它。

import { createTestingApp } from '@deepkit/framework';
import { AppCoreModule, MyService } from './app-core.ts';

test('service simple', async () => {
    const testing = createTestingApp({ imports: [new AppCoreModule] });

    const myService = testing.app.get(MyService);
    expect(myService.doIt()).toBe(true);
});

test('service simple big', async () => {
    // 针对特定测试场景更改模块的配置
    const testing = createTestingApp({
        imports: [new AppCoreModule({items: 100})]
    });

    const myService = testing.app.get(MyService);
    expect(myService.doIt()).toBe(true);
});
English中文 (Chinese)한국어 (Korean)日本語 (Japanese)Deutsch (German)