createWriteStream 的 ('error') 上的开玩笑单元测试

Posted

技术标签:

【中文标题】createWriteStream 的 (\'error\') 上的开玩笑单元测试【英文标题】:Jest unit test on('error') of createWriteStreamcreateWriteStream 的 ('error') 上的开玩笑单元测试 【发布时间】:2021-02-05 15:33:08 【问题描述】:

我正在使用 Nestjs,并编写了下面的函数,该函数从发布请求中接收文件并将其保存在我项目的文件夹中。 我的问题是我不确定如何测试 on('error') 分支。

单元测试函数。

  saveFile( createReadStream, filename : FileUpload): Promise<boolean> 
    return new Promise(async (resolve, reject) => 
      createReadStream().pipe(
        createWriteStream(join(process.cwd(), `apps/mull-api/uploads/$filename`))
          .on('finish', () => resolve(true))
          .on('error', () => 
            console.log(createReadStream);
            reject(false);
          )
      );
    );
  

我如何测试on('finish') 分支

  it('should save file', async () => 
    const returnedFile = await service.saveFile(mockFile);
    expect(returnedFile).toBe(true);
  );

这就是我的 mockFile 的样子。我尝试提供一个名称为空的 mockFile,但它出错了。

export const mockFile: FileUpload = 
  filename: 'zoro',
  mimetype: 'image/jpeg',
  encoding: '7bit',
  createReadStream(): ReadStream 
    return fs.createReadStream(join(process.cwd(), `apps/mull-api/uploads/mock-upload/zoro`));
  ,
;

【问题讨论】:

您在寻找单元测试还是集成测试? 你为什么在promise中使用异步函数? @slideshowp2 我正在尝试对这个函数进行单元测试。我需要在我的项目中达到 80% 的覆盖率阈值 @SyedMisharNewaz 我按照指南进行操作,这就是stephen-knutter.github.io/2020-02-07-nestjs-graphql-file-upload 【参考方案1】:

单元测试解决方案:

index.ts:

import  createWriteStream, ReadStream  from 'fs';
import  join  from 'path';

export interface FileUpload 
  filename: string;
  mimetype: string;
  encoding: string;
  createReadStream(): ReadStream;


export class FileService 
  public saveFile( createReadStream, filename : FileUpload): Promise<boolean> 
    return new Promise(async (resolve, reject) => 
      createReadStream().pipe(
        createWriteStream(join(process.cwd(), `apps/mull-api/uploads/$filename`))
          .on('finish', () => resolve(true))
          .on('error', () => 
            reject(false);
          ),
      );
    );
  

index.test.ts:

import  FileService, FileUpload  from './';
import  createWriteStream, WriteStream  from 'fs';
import  mocked  from 'ts-jest/utils';

jest.mock('fs');

describe('64485251', () => 
  afterAll(() => 
    jest.resetAllMocks();
    jest.clearAllMocks();
  );
  it('should save file', async () => 
    const mockReadStream =  pipe: jest.fn() ;
    const mockFile: FileUpload = 
      filename: 'zoro',
      mimetype: 'image/jpeg',
      encoding: '7bit',
      createReadStream: jest.fn().mockReturnValueOnce(mockReadStream),
    ;
    const mockWriteStream = 
      on: jest.fn().mockImplementation(function(this, event, handler) 
        if (event === 'finish') 
          handler();
        
        return this;
      ),
    ;
    mocked(createWriteStream).mockReturnValueOnce((mockWriteStream as unknown) as WriteStream);
    const service = new FileService();
    const actual = await service.saveFile(mockFile);
    expect(mockFile.createReadStream).toBeCalledTimes(1);
    expect(mockReadStream.pipe).toBeCalledTimes(1);
    expect(createWriteStream).toBeCalledWith(expect.stringContaining('apps/mull-api/uploads/zoro'));
    expect(mockWriteStream.on).toBeCalledWith('finish', expect.any(Function));
    expect(mockWriteStream.on).toBeCalledWith('error', expect.any(Function));
    expect(actual).toBeTruthy();
  );

  it('should handle error if save file failed', async () => 
    const mockReadStream =  pipe: jest.fn() ;
    const mockFile: FileUpload = 
      filename: 'zoro',
      mimetype: 'image/jpeg',
      encoding: '7bit',
      createReadStream: jest.fn().mockReturnValueOnce(mockReadStream),
    ;
    const mockWriteStream = 
      on: jest.fn().mockImplementation(function(this, event, handler) 
        if (event === 'error') 
          handler();
        
        return this;
      ),
    ;
    mocked(createWriteStream).mockReturnValueOnce((mockWriteStream as unknown) as WriteStream);
    const service = new FileService();
    await expect(service.saveFile(mockFile)).rejects.toEqual(false);
    expect(mockFile.createReadStream).toBeCalledTimes(1);
    expect(mockReadStream.pipe).toBeCalledTimes(1);
    expect(createWriteStream).toBeCalledWith(expect.stringContaining('apps/mull-api/uploads/zoro'));
    expect(mockWriteStream.on).toBeCalledWith('finish', expect.any(Function));
    expect(mockWriteStream.on).toBeCalledWith('error', expect.any(Function));
  );
);

单元测试结果:

 PASS  src/***/64485251/index.test.ts (10.201s)
  64485251
    ✓ should save file (6ms)
    ✓ should handle error if save file failed (3ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.ts |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        11.344s

【讨论】:

以上是关于createWriteStream 的 ('error') 上的开玩笑单元测试的主要内容,如果未能解决你的问题,请参考以下文章

fs.createwritestream 不是函数

Node.js:检测到一个文件,用 fs.createWriteStream() 打开,被删除

我可以从 fs.createWriteStream() 获取缓冲区吗?

Javascript Promise 无法解析 createWriteStream

javascript 带Node的CreateWriteStream

javascript 带Node的CreateWriteStream