node.js 中的单元测试流,jasmine

Unit testing streams in node.js, jasmine

我承诺会调用 HTTP get 来检索 ana csv 文件,这个 HTTP returns 我可以用作流的响应,我通过 csv 解析器传输响应,并认为另一个函数是可写流,然后我听一些事件。

但我的问题是测试这个,我的问题是我无法模拟对事件的调用,我不知道如何到达完成和错误中的代码。

这是检索文件并通过管道传输响应的代码段:

return new Promise((resolve, reject) => {
    https.get(url, async response => {
      response
        .pipe(this.csvParser)
        .pipe(crazyfunc)
        .on("finish", () => {
          logger.info("File process finished")
          resolve()
        })
        .on("error", (err: Error) => {
          if (err) {
            reject(err)
          }
        })
      resolve()
    })
  })

这是我的 .spec 文件,我按如下方式模拟此调用:

const response = {
    pipe: () => { },
    on: () => { }
};

beforeEach(async () => {
    spyOn(response, 'pipe').and.returnValue(response)
    spyOn(response, 'on').and.returnValue(response)
});

spyOn(https, 'get').and.callFake((url, func) => func(response))

单元测试解决方案如下:

index.js:

const https = require('https');

const crazyfunc = (v) => v;
const logger = console;

const obj = {
  csvParser(data) {
    return data;
  },

  fn() {
    const url = 'example.com';
    return new Promise((resolve, reject) => {
      https.get(url, async (response) => {
        response
          .pipe(this.csvParser)
          .pipe(crazyfunc)
          .on('finish', () => {
            logger.info('File process finished');
            resolve();
          })
          .on('error', (err) => {
            if (err) {
              reject(err);
            }
          });
      });
    });
  },
};

module.exports = obj;

index.test.js:

const obj = require('./');
const https = require('https');

describe('61121812', () => {
  it('should process file', async () => {
    const response = {
      pipe: jasmine.createSpy().and.callFake(function (processor) {
        processor();
        return this;
      }),
      on: jasmine.createSpy().and.callFake(function (event, callback) {
        if (event === 'finish') {
          callback();
        }
        return this;
      }),
    };
    const csvParserStub = spyOn(obj, 'csvParser');
    const getStub = spyOn(https, 'get').and.callFake((url, func) => func(response));
    await obj.fn();
    expect(getStub).toHaveBeenCalledWith('example.com', jasmine.any(Function));
    expect(csvParserStub).toHaveBeenCalled();
    expect(response.pipe).toHaveBeenCalledTimes(2);
    expect(response.on).toHaveBeenCalledTimes(2);
    expect(response.on).toHaveBeenCalledWith('finish', jasmine.any(Function));
    expect(response.on).toHaveBeenCalledWith('error', jasmine.any(Function));
  });

  it('should handle error', async () => {
    const response = {
      pipe: jasmine.createSpy().and.callFake(function (processor) {
        processor();
        return this;
      }),
      on: jasmine.createSpy().and.callFake(function (event, callback) {
        if (event === 'error') {
          const mError = new Error('network');
          callback(mError);
        }
        return this;
      }),
    };
    const getStub = spyOn(https, 'get').and.callFake((url, func) => func(response));
    await expectAsync(obj.fn()).toBeRejectedWithError('network');
    expect(getStub).toHaveBeenCalledWith('example.com', jasmine.any(Function));
    expect(response.pipe).toHaveBeenCalledTimes(2);
    expect(response.on).toHaveBeenCalledTimes(2);
    expect(response.on).toHaveBeenCalledWith('finish', jasmine.any(Function));
    expect(response.on).toHaveBeenCalledWith('error', jasmine.any(Function));
  });
});

带有覆盖率报告的单元测试结果:

Executing 2 defined specs...
Running in random order... (seed: 16491)

Test Suites & Specs:
(node:86448) ExperimentalWarning: The fs.promises API is experimental

1. 61121812
⠋    should process fileFile process finished
   ✔ should process file (17ms)
   ✔ should handle error (9ms)

>> Done!


Summary:

  Passed
Suites:  1 of 1
Specs:   2 of 2
Expects: 12 (0 failures)
Finished in 0.046 seconds

---------------|---------|----------|---------|---------|-------------------
File           | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
---------------|---------|----------|---------|---------|-------------------
All files      |     100 |    83.33 |     100 |     100 |                   
 index.js      |     100 |       50 |     100 |     100 | 23                
 index.test.js |     100 |      100 |     100 |     100 |                   
---------------|---------|----------|---------|---------|-------------------

源代码:https://github.com/mrdulin/jasmine-examples/tree/master/src/Whosebug/61121812