【问题标题】:Mock FTP Connection Ready and Error event Node Typescript模拟 FTP 连接就绪和错误事件节点打字稿
【发布时间】:2021-08-29 06:26:09
【问题描述】:

我正在使用FTP 库建立 FTP 连接以从特定位置获取文件。我正在编写一个基于 Node-Typescript-Express 的应用程序。在创建单元测试用例时,我试图模拟库以覆盖在就绪事件和错误事件下编写的代码。以下是我尝试使用的方法。

代码:

import * as Client from "ftp"
c = new Client()
c.on('ready', () => {
    c.list((err, list) => {
      if (err) throw err;
      //my code is here 
      c.end();
});
});
c.on("error",()=>{
   //my code is here
})
// connect to localhost:21 as anonymous
c.connect();

测试用例方法 1:

import * as Client from "ftp";
c = new Client()
jest.spyOn(c,"connect")
jest.spyOn(c, "on")
  .mockImplementation()
  .mockResolvedValue((new EventEmitter).emit("ready"));

测试用例方法 2:

import * as Client from "ftp";
c = new Client()
sinon.stub(Client.prototype, 'connect').withArgs().callsFake(()=>{
  (new EventEmitter).emit("ready"); 
});

测试用例方法 3:

const connectMock = jest.fn()=>mockResult;

jest.mock("ftp",() =>({
connection:{
    cwd: jest.fn(),
    on: jest.fn(),
    connect: connectMock,
}
})) //not further

如果有人能建议我一个有效的方法或我迄今为止使用的方法的变化,我需要帮助。这样我就可以在连接建立的情况下覆盖为ready/error 事件编写的代码。提前致谢。

【问题讨论】:

  • 使用 jestjs 方法得到了什么?
  • 没有,覆盖范围保持不变。

标签: node.js typescript express unit-testing jestjs


【解决方案1】:

您可以使用jest.mock(moduleName, factory, options) 模拟ftp 包及其Client 类。

由于您的代码是在模块范围内定义的,因此您的代码将在导入模块时执行。我们需要在导入模块之前创建模拟对象。

另外,我在error事件处理程序中使用console.log来代表你的具体代码实现。

例如

index.ts:

import Client from 'ftp';

const c = new Client();

c.on('ready', () => {
  c.list((err, list) => {
    if (err) throw err;
    c.end();
  });
});
c.on('error', () => {
  console.log('handle error');
});
c.connect();

index.test.ts:

const mc = {
  on: jest.fn(),
  list: jest.fn(),
  end: jest.fn(),
  connect: jest.fn(),
};
jest.mock('ftp', () => {
  return jest.fn(() => mc);
});

describe('67951757', () => {
  beforeEach(() => {
    jest.resetModules();
  });
  afterAll(() => {
    jest.resetAllMocks();
  });
  afterEach(() => {
    jest.clearAllMocks();
  });
  it('should handle ready', async () => {
    mc.on.mockImplementation(function (event, handler) {
      if (event === 'ready') {
        handler();
      }
      return mc;
    });
    mc.list.mockImplementation((callback) => {
      callback(null as any, []);
    });
    await import('./');
    expect(mc.on).toBeCalledWith('ready', expect.any(Function));
    expect(mc.on).toBeCalledWith('error', expect.any(Function));
    expect(mc.connect).toBeCalledTimes(1);
    expect(mc.list).toBeCalledWith(expect.any(Function));
    expect(mc.end).toBeCalledTimes(1);
  });

  it('should handle list error', async () => {
    mc.on.mockImplementation(function (event, handler) {
      if (event === 'ready') {
        handler();
      }
      return mc;
    });
    mc.list.mockImplementation((callback) => {
      callback(new Error('memory leak'));
    });
    await expect(() => import('./')).rejects.toThrow('memory leak');
    expect(mc.on).toBeCalledWith('ready', expect.any(Function));
    expect(mc.list).toBeCalledWith(expect.any(Function));
    expect(mc.end).not.toBeCalled();
  });

  it('should handle error', async () => {
    mc.on.mockImplementation(function (event, handler) {
      if (event === 'error') {
        handler();
      }
      return mc;
    });
    mc.list.mockImplementation((callback) => {
      callback(null as any, []);
    });
    const logSpy = jest.spyOn(console, 'log');
    await import('./');
    expect(mc.on).toBeCalledWith('error', expect.any(Function));
    expect(mc.list).not.toBeCalled();
    expect(logSpy).toBeCalledWith('handle error');
    logSpy.mockRestore();
  });
});

测试结果:

 PASS  examples/67951757/index.test.ts (9.59 s)
  67951757
    ✓ should handle ready (7869 ms)
    ✓ should handle list error (4 ms)
    ✓ should handle error (19 ms)

  console.log
    handle error

      at console.<anonymous> (node_modules/jest-mock/build/index.js:845:25)

----------|---------|----------|---------|---------|-------------------
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:       3 passed, 3 total
Snapshots:   0 total
Time:        10.802 s

【讨论】:

  • 感谢@slideshowp2,我模拟了这两个事件。这很有帮助。再次感谢。
猜你喜欢
  • 1970-01-01
  • 2020-05-30
  • 1970-01-01
  • 2021-01-21
  • 2018-04-20
  • 1970-01-01
  • 2020-11-21
  • 2016-05-31
  • 2017-11-07
相关资源
最近更新 更多