单元测试控制器 NestJs 中的模拟文件上传

Mock file upload in unit test controller NestJs

我在嵌套 js 控制器中有一个方法,它带有两个参数,如下所示:

@UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(MemberType.OWNER)
  @Post('')
  @UseInterceptors(
    FilesInterceptor('images', 4, {
      storage: fileStorageProductImage,
      fileFilter: fileFilter,
      limits: fileSizeLimit,
    }),
  )
  @UseInterceptors(new MulterInterceptor('images'))
  public async addProduct(
    @Req()
    req: Request,
    @UploadedFiles() files: Express.Multer.File[],
  ) {
  
  //code
  //
  }

这是我的单元测试

describe('Unit testing path 1', () => {
      const MemberServiceProvider = {
        provide: MemberService,
        useClass: MemberServiceStub,
      };
      beforeEach(async () => {
        const module: TestingModule = await Test.createTestingModule({
          controllers: [ProductsController],
          providers: [MemberServiceProvider],
        }).compile();
        controller = module.get<ProductsController>(ProductsController);
      });
      //
      const result = controller.addProduct(..., ...);
    });

我目前不知道要将什么传递给 addProduct 方法,因为我不知道如何模拟请求对象和 Express.Multer.File[]。提前致谢

致所有仍在寻找答案的人。我只是想知道如何解决这个问题。首先,我们需要定义一个方法,该方法可用于通过流从本地机器读取文件。

const fileToBuffer = (filename) => {
  const readStream = fs.createReadStream(filename);
  const chunks = [];
  return new Promise((resolve, reject) => {
    // Handle any errors while reading
    readStream.on('error', (err) => {
      // handle error

      // File could not be read
      reject(err);
    });

    // Listen for data
    readStream.on('data', (chunk) => {
      chunks.push(chunk);
    });

    // File is done being read
    readStream.on('close', () => {
      // Create a buffer of the image from the stream
      resolve(Buffer.concat(chunks));
    });
  });
};

然后,我们在单元测试中调用该方法

const imageBuffer = (await fileToBuffer(
          __dirname + 'path-to-file',
        )) as Buffer;

在我们的控制器中,上传的文件具有 Express.Multer.File[] 类型,因此我们必须创建与上述类型相同的变量。

const imageFiles: Express.Multer.File[] = [];
        const myReadableStreamBuffer = new streamBuffers.ReadableStreamBuffer({
          frequency: 10, // in milliseconds.
          chunkSize: 2048, // in bytes.
        });
        myReadableStreamBuffer.put(imageBuffer as Buffer);
        imageFiles.push({
          buffer: imageBuffer,
          fieldname: 'fieldname-defined-in-@UseInterceptors-decorator',
          originalname: 'original-filename',
          encoding: '7bit',
          mimetype: 'file-mimetyp',
          destination: 'destination-path',
          filename: 'file-name',
          path: 'file-path',
          size: 955578,
          stream: myReadableStreamBuffer,
        });

最后,我们可以使用新创建的 imagesFiles 变量作为参数调用我们的 addProduct 方法。