【问题标题】:Not able to figure out issue in jest code coverage无法找出笑话代码覆盖率的问题
【发布时间】:2022-02-10 07:38:25
【问题描述】:

我的nestjs中有以下文件。

import { extname } from 'path';
import { diskStorage } from 'multer';
import { v4 as uuid } from 'uuid';
import { HttpException, HttpStatus } from '@nestjs/common';

export const multerConfig = {
    dest: process.env.UPLOAD_LOCATION,
};

export const multerOptions = {
    limits: {
        fileSize: +process.env.MAX_FILE_SIZE,
    },
    fileFilter: (_req: any, file: any, cb: any) => {
        if (file.mimetype.match(/\/(jpg|jpeg|png|gif|pdf|msg|eml)$/)) {
            cb(null, true);
        } else {
            cb(
                new HttpException(
                    `Unsupported file type ${extname(file.originalname)}`,
                    HttpStatus.BAD_REQUEST
                ),
                false
            );
        }
    },
    storage: diskStorage({
        destination: multerConfig.dest,
        filename: (_req: any, file: any, cb: any) => {
            cb(null, `${uuid()}${extname(file.originalname)}`);
        },
    }),
};

我为它写了下面的测试用例。

import { Readable } from 'stream';
import { multerConfig, multerOptions } from './multer.config';

describe('Multer Configuration ', () => {
    const mockFile: Express.Multer.File = {
        filename: '',
        fieldname: '',
        originalname: '',
        encoding: '',
        mimetype: '',
        size: 1,
        stream: new Readable(),
        destination: '',
        path: '',
        buffer: Buffer.from('', 'utf8'),
    };
    it('should define destination', () => {
        expect(multerConfig).toBeDefined();
        expect(multerConfig.dest).toBe(process.env.UPLOAD_LOCATION);
    });

    it('should define multer upload options', async () => {
        expect(multerOptions).toBeDefined();
        expect(multerOptions.fileFilter).toBeDefined();
        expect(multerOptions.storage).toBeTruthy();
        expect(multerOptions.limits).toBeTruthy();

        const cb = jest.fn();
        multerOptions.fileFilter({}, mockFile, cb);
        expect(cb).toHaveBeenCalled();
        expect(cb).toHaveBeenCalledTimes(1);
        expect(cb()).toBeFalsy();
    });

    afterAll(() => {
        jest.resetAllMocks();
    });
});

两个测试用例都成功,但是当我检查代码覆盖率时,它只显示 50%。它显示行 1631 未覆盖。

第 16 行是

 cb(null, true); it comes inside the `if` block

第 31 行是

 cb(null, `${uuid()}${extname(file.originalname)}`);

您能帮我介绍一下这部分吗?我真的很挣扎。 我需要额外的测试用例还是需要修改现有的测试用例?

编辑1:-

 const fileType = 'jpg';

    it('should define filetype', async () => {
        const cb = jest.fn();
        process.env.FILE_TYPE = 'jpg';
        multerOptions.fileFilter({}, mockFile, cb);
        expect(cb).toHaveBeenCalled();
        expect(cb).toHaveBeenCalledTimes(1);
        expect(cb()).toBeFalsy();
    });

测试用例获得成功。但覆盖范围和线路仍然相同

【问题讨论】:

  • 请更改标题,以便未来的搜索者可以从中受益。想象一下,如果您遇到这个问题,您会在搜索引擎中添加什么?
  • 另请注意,代码覆盖率与通过的测试数量无关。它会告诉您测试涵盖了哪些代码。
  • 我一定会这样做的。关于测试那条线有什么帮助吗?
  • 即使是很小的帮助或建议也会很有帮助。请帮忙

标签: javascript node.js unit-testing jestjs nestjs


【解决方案1】:

您的第一个未涵盖的代码部分来自您对 mime 类型使用模式匹配这一事实。

if (file.mimetype.match(/\/(jpg|jpeg|png|gif|pdf|msg|eml)$/)) {
            cb(null, true);
}

因此,您需要创建一个测试,以使用其中一种 mime 类型创建模拟文件。

例如,如下所示。虽然,在良好的测试设置中,您可能希望将所有这些扩展作为测试用例进行测试。也许使用某种表格驱动的测试方法。

const mockFile: Express.Multer.File = {
        mimetype: 'jpg',
        // other stuff 
};

似乎在您的测试中,函数总是进入 else 块,这会引发 HTTP 异常。

您的第二个问题是您在测试中没有使用 options.storage。并且您还提供了一些可以调用函数的选项。

您可以在测试中像下面这样调用它。

const upload = multer(multerOptions).single('somefile');

如果您不想这样做,可以将回调移动到命名函数中并分配它。

export function filename(_req: any, file: any, cb: any) {
    cb(null, `${uuid()}${extname(file.originalname)}`);
}

export const multerOptions = {
    storage: diskStorage({
        destination: multerConfig.dest,
        filename,
    }),
}

然后您可以在测试设置中自行测试文件名功能。

或者您找到一种方法来自行调用存储对象上的文件名函数。我不知道multer,所以我不知道这是否可能。您需要查阅文档。

总的来说,这可能看起来像这样。

import { extname } from 'path';
import { diskStorage } from 'multer';
import { v4 as uuid } from 'uuid';
import { HttpException, HttpStatus } from '@nestjs/common';

export const multerConfig = {
    dest: process.env.UPLOAD_LOCATION,
};

export function filename(_req: any, file: any, cb: any) {
            cb(null, `${uuid()}${extname(file.originalname)}`);
};

export const multerOptions = {
    limits: {
        fileSize: +process.env.MAX_FILE_SIZE,
    },
    fileFilter: (_req: any, file: any, cb: any) => {
        if (file.mimetype.match(/\/(jpg|jpeg|png|gif|pdf|msg|eml)$/)) {
            cb(null, true);
        } else {
            cb(
                new HttpException(
                    `Unsupported file type ${extname(file.originalname)}`,
                    HttpStatus.BAD_REQUEST
                ),
                false
            );
        }
    },
    storage: diskStorage({
        destination: multerConfig.dest,
        filename,
    }),
};

然后在你的测试中像这样。

import { Readable } from 'stream';
import { multerConfig, multerOptions, filename } from './multer.config';

describe('Multer Configuration ', () => {
    const mockFile: Express.Multer.File = {
        filename: 'foo.jpg', // give it a name
        fieldname: '',
        originalname: '',
        encoding: 'utf8',
        mimetype: 'jpg', // give it a mime type
        size: 1,
        stream: new Readable(),
        destination: '',
        path: '',
        buffer: Buffer.from('', 'utf8'),
    };
    it('should define destination', () => {
        expect(multerConfig).toBeDefined();
        expect(multerConfig.dest).toBe(process.env.UPLOAD_LOCATION);
    });

    it('should define multer upload options', async () => {
        expect(multerOptions).toBeDefined();
        expect(multerOptions.fileFilter).toBeDefined();
        expect(multerOptions.storage).toBeTruthy();
        expect(multerOptions.limits).toBeTruthy();
    });
    
    // test the filter
    it('should filter the file based on mimetype', () => {
        const cb = jest.fn();
        multerOptions.fileFilter({}, mockFile, cb);
        // do something with the callback
    });
    
    // test the filename
    it('should create the proper filename', () => {
        const cb = jest.fn();
        filename({}, mockfile, cb)
        // do something with the callback
    });


    afterAll(() => {
        jest.resetAllMocks();
    });
});

我不确定如何使用 jest 或您实际想要测试的内容。但是像这样,这条线应该被覆盖。但从这个意义上说,覆盖并没有多大意义。像这样的测试并不好。你应该弄清楚你想要测试的究竟是什么。这只是为了表明您大致需要。

【讨论】:

  • 谢谢。如何在测试用例中合并文件类型更改?因为我做了同样的事情,但还是一样的行来了,而且它没有出现在报道中。
  • @Oze,文件类型是什么意思?
  • 过滤器将检查 mime 类型。如果你的模拟文件没有,你最终会进入 else 块。
  • @Oze,我已经更新了我的答案。
  • 也许你的匹配器关闭了/\/(jpg|jpeg|png|gif|pdf|msg|eml)$/,为什么你的开头有斜线?它应该看起来像这样/^(jpg|jpeg|png|gif|pdf|msg|eml)$/ 而且它不能是相同的,因为函数已经移动了。文件名覆盖率一定有所改变。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-08
  • 2019-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多