用vscode进行jest单元测试并调试代码

无人久伴 提交于 2020-05-02 11:38:14

首先需要安装相应的包:npm i -D jest ts-jest supertest jest-express jest-sonar-reporter sonarqube-scanner

 

1、单元测试:npm run test

2、代码覆盖率:npm run test:cov

3、使用SonarQube平台分析:npm run sonar,完成后就可以使用SonarQube web查看相关数据

4、如何调试单元测试的代码,有二种方法:1、在vscode终端运行npm run test:debug,2、在vscode的launch.json中添加相应的代码,然后就右直接选择运行中的Debug Jest Tests来启动

 

在pageage.json增加如下配置

 1 "scripts": {
 2     "lint": "eslint 'src/**/*.{ts,js}'",
 3     "lint:fix": "eslint 'src/**/*.{ts,js}' --fix",
 4     "lint:ts": "tslint -p tsconfig.json -c tslint.json",
 5     "test": "jest --runInBand --forceExit --colors",
 6     "test:watch": "jest --watch",
 7     "test:cov": "jest --coverage",
 8     "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
 9     "test:e2e": "jest --runInBand --config ./test/jest-e2e.json",
10     "sonar": "node sonar-project.js"
11   },
12 "engines": {
13     "node": ">=8.9.0"
14   },
15   "jest": {
16     "moduleFileExtensions": [
17       "js",
18       "json",
19       "ts"
20     ],
21     "moduleNameMapper": {
22       "^@creative(.*)$": "<rootDir>/modules/creative$1",
23       "^@admin(.*)$": "<rootDir>/modules/admin$1",
24       "^@configuration(.*)$": "<rootDir>/modules/configuration$1",
25       "^@common(.*)$": "<rootDir>/common$1",
26       "^@auth(.*)$": "<rootDir>/modules/auth$1"
27     },
28     "rootDir": "src",
29     "testRegex": ".spec.ts$",
30     "transform": {
31       "^.+\\.(t|j)s$": "ts-jest"
32     },
33     "collectCoverageFrom": [
34       "**/*.(t|j)s"
35     ],
36     "testResultsProcessor": "jest-sonar-reporter",
37     "coverageDirectory": "../coverage",
38     "coveragePathIgnorePatterns": [
39       "/node_modules/"
40     ],
41     "testEnvironment": "node"
42   },
43   "jestSonar": {
44     "reportPath": "coverage",
45     "reportFile": "test-reporter.xml",
46     "indent": 4
47   }

 

sonar-project.js

const sonarqubeScanner = require('sonarqube-scanner');
const parameters = {
    serverUrl:  'http://localhost:9000',
    token: 'XXX',
    options : {
        'sonar.projectVersion': '1.1',
        'sonar.projectName': 'create-server',
        'sonar.projectKey': 'create-server',
        'sonar.sourceEncoding': 'UTF-8',
        'sonar.scm.provider': 'git',
        'sonar.language': 'typescript',
        'sonar.sources': 'src',
        'sonar.inclusions': 'src/**',
        'sonar.exclusions': '**/node_modules/**,**/coverage/**',
        'sonar.tests': 'test',
        'sonar.ts.tslint.configPath': 'tslint.json',
        'sonar.test.inclusions': 'src/**/*.spec.ts,test/**/*.e2e-spec.ts',
        'sonar.testExecutionReportPaths':  'coverage/test-reporter.xml',
        'sonar.javascript.lcov.reportPaths': 'coverage/lcov.info',
    }
}
sonarqubeScanner(parameters, () => process.exit());

 

示例代码  

 1 import { Test, TestingModule } from '@nestjs/testing';
 2 import { AppController } from './app.controller';
 3 import { AppService } from './app.service';
 4 import { ApplicationModule } from './app.module';
 5 import { Request } from 'jest-express/lib/request';
 6 import { Response } from 'jest-express/lib/response';
 7 
 8 describe('AppController', () => {
 9     let appController: AppController, appService: AppService, req: Request, res: Response;
10 
11     beforeAll(async () => {
12         const module: TestingModule = await Test.createTestingModule({
13             imports: [ApplicationModule],
14         }).compile();
15 
16         appController = module.get<AppController>(AppController);
17         appService = module.get<AppService>(AppService);
18         req = new Request();
19         res = new Response();
20     });
21 
22     describe('controller test', () => {
23         it('Mock一个函数返回动态测试数据', () => {
24             expect.assertions(1);
25 
26             // 通过jest.fn()来Mock一个回调函数返回测试数据
27             const mockfn = jest.fn();
28             const result = mockfn.mockReturnValue(`[${new Date()}]: Welcome to use youtu test service.`);
29 
30             // 调用Controller的root方法,root方法调用service里的root方法返回相应的结果与mock结果是否达到预期
31             expect(appController.root()).toBe(result());
32         });
33 
34         it('监听函数是否被正常调用', async (done) => {
35             // 验证第二个断言被调用,测试异步代码时这通常很有用
36             expect.assertions(3);
37             const spyfn = jest.spyOn(appService, 'getAllUsers');
38             req.setBody({ name: 'mock data' });
39             expect(await appController.getAllUsers(req, res)).toBe('test service');
40             // 用来判断一个函数是否被调用过
41             expect(spyfn).toHaveBeenCalled();
42 
43             // 判断函数被调用过几次
44             expect(spyfn).toHaveBeenCalledTimes(1);
45             done();
46         });
47 
48         it('Mock函数调用', async (done) => {
49             // 验证第二个断言被调用,测试异步代码时这通常很有用
50             expect.assertions(3);
51             const resultMock = Promise.resolve('test mock');
52 
53             // 监听并Mock掉appService.getAllUsers函数的返回结果,当这个函数有依赖第三方的时候可以使用
54             const spyfn = jest.spyOn(appService, 'getAllUsers').mockImplementation(() => resultMock);
55             expect(await appController.getAllUsers(req, res)).toBe('test mock');
56 
57             // 用来判断一个函数是否被调用过
58             expect(spyfn).toHaveBeenCalled();
59 
60             // 判断函数被调用过几次
61             expect(spyfn).toHaveBeenCalledTimes(2);
62             done();
63         });
64 
65         it('promise throws', async (done) => {
66             expect.assertions(1);
67             const message = 'test service error';
68             const result2 = Promise.reject(new Error(message));
69 
70             // 劫持getAllUsers函数并返回一个异常给appController
71             jest.spyOn(appService, 'getAllUsers').mockImplementation(() => result2);
72             await expect(appController.getAllUsers(req, res)).rejects.toThrow(message);
73             done();
74         });
75     });
76 });

 

配置vscode调试

 1 {
 2     // 使用 IntelliSense 了解相关属性。
 3     // 悬停以查看现有属性的描述。
 4     // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
 5     "version": "0.2.0",
 6     "configurations": [
 7         {
 8             "name": "Debug TypeScript",
 9             "type": "node",
10             "request": "launch",
11             "env": {
12                 "NODE_ENV": "development"
13             },
14             "runtimeExecutable": "nodemon",
15             "restart": true,
16             "args": [
17                 "${workspaceRoot}/src/main.ts"
18             ],
19             "runtimeArgs": [
20                 "--config",
21                 " nodemon-debug.json",
22                 "--nolazy",
23                 "-r",
24                 "ts-node/register"
25             ],
26             "sourceMaps": true,
27             "disableOptimisticBPs": true,
28             "cwd": "${workspaceRoot}",
29             "protocol": "inspector",
30             "console": "integratedTerminal",
31             "internalConsoleOptions": "neverOpen"
32         },
33         {
34             "type": "node",
35             "request": "launch",
36             "name": "Debug Jest Tests",
37             "program": "${workspaceFolder}/node_modules/.bin/jest",
38             "args": [
39                 "-r tsconfig-paths/register",
40                 "-r ts-node/register",
41                 "--runInBand"
42             ],
43             "console": "integratedTerminal",
44             "internalConsoleOptions": "neverOpen",
45             "disableOptimisticBPs": true,
46             "skipFiles": [
47                 "<node_internals>/**"
48             ],
49         },
50         {
51             "type": "node",
52             "request": "launch",
53             "name": "Debug Jest File",
54             "program": "${workspaceFolder}/node_modules/.bin/jest",
55             "args": [
56                 "${fileBasenameNoExtension}",
57                 "-r tsconfig-paths/register",
58                 "-r ts-node/register",
59                 "--runInBand"
60             ],
61             "console": "integratedTerminal",
62             "internalConsoleOptions": "neverOpen",
63             "disableOptimisticBPs": true,
64         },
65     ]
66 }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!