nestjs 單元測試

啓動單元測試

zengwe$ npm run test

運行效果

 PASS  src/admin/controllers/zeng-Try.controller.spec.ts      

Test Suites: 1 skipped, 14 passed, 14 of 15 total
Tests:       7 skipped, 57 passed, 64 total
Snapshots:   0 total
Time:        7.422s, estimated 10s
Ran all test suites related to changed files.

Watch Usage: Press w to show more.

controller單元測試

import { Body, Controller, Post, Get, Put, Delete, Query } from '@nestjs/common';
import { isNullOrUndefined } from 'util';
import { code } from '../../common/code';
import { zengTryService } from '../services/zeng-Try.service';
import { AddForm, UpdateForm, DeleteForm} from './zeng-Try.form';
import { ValidationPipe } from '../../pipes/validation.pipe';
@Controller({
    path: '/api/zeng/Try'
})
export class zengTryController {
    constructor(protected zengTrySrv: zengTryService) {

    }
    @Get('/all')
    async getAll() {
        let list = await this.zengTrySrv.getAll();
        return {code: code.success, data: {list: list}};
    }
    @Post()
    async add(@Body(new ValidationPipe()) form: AddForm) {
        let res = await this.zengTrySrv.addTry(form);
        return {code: code.success, data: res};
    }
    @Put()
    async update(@Body(new ValidationPipe()) form: UpdateForm) {
        let res = await this.zengTrySrv.updateTry(form);
        return {code: code.success, data: res};
    }
    @Delete()
    async delete(@Query(new ValidationPipe()) form: DeleteForm) {
        let res = await this.zengTrySrv.deleteTry(form.id);
        return {code: code.success, data: res};
    }
}

@Body(new ValidationPipe() 爲表單驗證的中間件不是單元測試的重點,反正表單不合格就返回對應錯誤

import { INestApplication, MiddlewareConsumer, Module, NestModule, Controller, Get, Post, Header, Session, Injectable, NestMiddleware, Logger, HttpException, HttpStatus } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { code } from '../../common/code';
import { zengTryController } from './zeng-Try.controller';
import { zengTryService } from '../services/zeng-Try.service';
import * as request from 'supertest';
const apiPrefix = '/api/admin/zeng/Try';
describe('zeng Try controller', () => {
    let app: INestApplication;
    beforeAll(async () => {
        const module = await Test.createTestingModule({
            imports: [],
            controllers: [zengTryController],
            providers: [
                {
                    provide: zengTryService,
                    useValue: {
                        getAll: () => {
                            return Promise.resolve([]);
                        },
                        addTry: (data) => {
                            return Promise.resolve(data);
                        },
                        updateTry: () => {
                            return Promise.resolve({});
                        },
                        deleteTry: () => {
                            return Promise.resolve(null);
                        }
                    }
                }
            ]
        })
            .compile();
        app = module.createNestApplication();
        await app.init();
    });
    it('get All', (done) => {
        request(app.getHttpServer())
        .get(apiPrefix+'/all')
        .expect(200)
        .end(function (err, res) {
            expect(res.body.code).toEqual(code.success);
            done();
        });
    });
    it('add form error test', (done) => {
        request(app.getHttpServer())
        .post(apiPrefix)
        .expect(200)
        .end(function (err, res) {
            expect(res.body.code).toEqual(code.formErr);
            expect(Object.prototype.toString.call(res.body.data)).toEqual('[object Array]');
            done();
        });
    });
    it('add Try', (done) => {
        request(app.getHttpServer())
        .post(apiPrefix)
        .send({
            apiName: 'dd3', 
            alias: 'cc3s',
            isVip: true,
            isNormal: true,
            isEducation: true,
            isTest: true,
            isPublic: true
        })
        .expect(201)
        .end((err, res) => {
            expect(res.body.code).toEqual(code.success);
            expect(Object.prototype.toString.call(res.body.data)).toEqual('[object Object]');
            done();
        });
    });
    it('update Try no id', (done) => {
        request(app.getHttpServer())
        .put(apiPrefix)
        .send({apiName: 'fdsafd'})
        .expect(200)
        .end((err, res) => {
            expect(res.body.code).toEqual(code.formErr);
            done();
        })
    });
    it('update Try', (done) => {
        request(app.getHttpServer())
        .put(apiPrefix)
        .send({apiName: 'fdsafd', id: 1})
        .expect(200)
        .end((err, res) => {
            expect(res.body.code).toEqual(code.success);
            done();
        })
    });
    it('delete Try', (done) => {
        request(app.getHttpServer())
        .delete(apiPrefix)
        .query({id: 1})
        .expect(200)
        .end((err, res) => {
            expect(res.body.code).toEqual(code.success);
            done();
        })
    });
});

createTestingModule相當於@Module()需要什麼就添加什麼。

it(string,function);中function是支持async/await的,done爲可選參數

測試目標爲僅僅這個controller,所以對於依賴的service用一個假的替換掉,認爲這個service是完美的。至於service真實情況是否完美,那放到對應的service中去測試;

上面還缺少一個文件上傳

it('upload', async (done) => {
        let fileStre = new stream();
        let req = request(app.getHttpServer()).post('/file/upload')
        .field('FileHash', UUID.v4())
        .attach('Chunk', Buffer.alloc(1024, 'fsfs', 'binary'), {filename: 'dd.txt'})
        .expect(201)
        .end((err, res) => {
            done();
        });
    })

field 相當於application/form中的的普通字段,attach爲文件,如果最後一個filename不添加也是可以傳上去,只是有的框架會出些問題

service的單元測試

import { Injectable, Inject } from '@nestjs/common';
import { userAppProvidersName, UserApp } from '../../models/user-app.model';
import { Op, where } from 'sequelize';
import { zengtestTry, zengtestTryProvidersName} from '../../models/zeng-testTry.model';

@Injectable()
export class zengtestTryService {
    constructor(@Inject(zengtestTryProvidersName) public readonly zengtestTryRepository: typeof zengtestTry) {

    }
    async getAll(): Promise<zengtestTry[]> {
        let res: zengtestTry[] = await this.zengtestTryRepository.findAll();
        return res;
    }
    async addtestTry(data: ItestTry): Promise<zengtestTry> {
        let res = await this.zengtestTryRepository.build(data).save();
        return res;
    }
    async updatetestTry(data: {id: number}&Partial<ItestTry>): Promise<number> {
        let res = await this.zengtestTryRepository.update(data, {where: {id: data.id}});
        return res;
    }
    async deletetestTry(id: number): Promise<void> {
        let res = await this.zengtestTryRepository.destroy({where: {id: id}});
    }
}
interface ItestTry {
    name: string;
}

測試文件

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { DatabaseModule } from '../../database/database.module';
import { v4 } from 'uuid';
import { where } from 'sequelize/types';
import { zengtestTryProvider } from '../../models/zeng-testTry.model';
import { zengtestTryService } from './zeng-testTry.service';

describe('zeng testTry service', () => {
    let service: zengtestTryService;
    let module: TestingModule;
    beforeAll(async () => {
        module = await Test.createTestingModule({
            imports: [
                DatabaseModule
            ],
            providers: [
                zengtestTryProvider,
                zengtestTryService
            ]
        }).compile();
        service = module.get<zengtestTryService>(zengtestTryService);
    });
    it('init service', () => {
        expect(service != null).toEqual(true);
    });
    it("add testTry", async () => {
        let res =  await service.addtestTry({
            apiName: 'addTest',
            alias: 'addAlias',
            isVip: true,
            isNormal: true,
            isEducation: true,
            isTest: true,
            isPublic: true
        });
        await service['zengtestTryRepository'].destroy({where: {id: res.id}});
        expect(res.apiName).toEqual('addTest');
    });
    it('update testTry', async () => {
        let res =  await service.addtestTry({
            apiName: 'addTest2',
            alias: 'addAlias',
            isVip: true,
            isNormal: true,
            isEducation: true,
            isTest: true,
            isPublic: true
        });
        await service.updatetestTry({id: res.id, alias: 'updataAlias'});
        let afterUpdateData =  await service['zengtestTryRepository'].findOne({where: {id: res.id}});
        expect(afterUpdateData.alias).toEqual('updataAlias');
        await service['zengtestTryRepository'].destroy({where: {id: res.id}});
    });
    it('delete testTrys', async () => {
        let res =  await service.addtestTry({
            apiName: 'deleteTest',
            alias: 'addAlias',
            isVip: true,
            isNormal: true,
            isEducation: true,
            isTest: true,
            isPublic: true
        });
        let del = await service.deletetestTry(res.id);
        let find = await service['zengtestTryRepository'].findOne({where: {id: res.id}});
        expect(find).toEqual(null);
    });
    it('get all', async () => {
        let res =  await service.addtestTry({
            apiName: 'get all test',
            alias: 'addAlias',
            isVip: true,
            isNormal: true,
            isEducation: true,
            isTest: true,
            isPublic: true
        });
        let res2 =  await service.addtestTry({
            apiName: 'get all Test2',
            alias: 'addAlias',
            isVip: true,
            isNormal: true,
            isEducation: true,
            isTest: true,
            isPublic: true
        });
        let list = await service.getAll();
        await service['zengtestTryRepository'].destroy({where: {id: res.id}});
        await service['zengtestTryRepository'].destroy({where: {id: res2.id}});
        expect(list.length).toEqual(2);
        let names = [list[0].apiName, list[1].apiName];
        expect(names.indexOf('get all test') != -1 && names.indexOf('get all Test2') != -1).toEqual(true);
    });
});

好像挺簡單的

總結

單元測試的的核心思想就是隻管好自己,外部引入都用假的,默認認爲都是正常執行,每一個測試都是正常得到期望值,那麼整體也就是正常了

發佈了99 篇原創文章 · 獲贊 20 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章