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


    首先需要安装相应的包: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 }
  • 相关阅读:
    web前端知识体系大全【欢迎补充】
    ESA2GJK1DH1K基础篇: 阿里云物联网平台: 云平台显示单片机采集的温湿度数据,控制设备继电器(基于ESP8266,AT指令TCP_MQTT通信)(V0.1)
    ESA2GJK1DH1K基础篇: 阿里云物联网平台: 使用阿里云物联网平台提供的物理模型Topic通信控制(ESP8266,TCP透传指令)
    ESA2GJK1DH1K基础篇: 阿里云物联网平台: 使用阿里云物联网平台提供的自定义Topic通信控制(ESP8266,TCP透传指令)
    ESA2GJK1DH1K基础篇: 关于各大物联网平台的MQTT通信
    ESA2GJK1DH1K微信小程序篇: 小程序连接MQTT简单的Demo
    Android 开发基础入门: Android Studio 导入工程
    Android 开发基础入门: android studio安装教程
    ESA2GJK1DH1K升级篇: 移植远程更新程序到STM32F103RET6型号的单片机,基于(GPRS模块AT指令TCP透传方式)
    【传输协议】http协议GET与POST传递数据的最大长度能够达到多少
  • 原文地址:https://www.cnblogs.com/terrylin/p/12813970.html
Copyright © 2020-2023  润新知