带有回调函数的Mock Node模块。

问题描述 投票:0回答:1

我有一些代码,使用 ssh-exec,一个节点模块,以其回调形式。

const sshExec = require('ssh-exec');

const myCodeThatUsesSshExec = (arg1,arg2,arg3) => new Promise((resolve, reject) => {
  sshExec('ls -lh', '[email protected]', function (err, stdout, stderr) {
  if(err) {
    reject(err);
  } else if(stderr) {
    reject(stderr);
  } else {
   // process stdout
   const results = process stdout into an array...
   resolve(results);
  }
})
});

我试图测试我的代码,但我不知道如何模拟回调函数以返回模拟数据。这是我目前的尝试

const myCodeThatUsesSshExec = require('./my-code');
jest.mock('ssh-exec');

test('ssh test', async () => {
    const resp = `total 268K
-rw-rw-rw- 1 bob bob 369 Jun 12 15:00 Dockerfile
-rw-rw-rw- 1 bob bob 849 Jun 12 14:46 app.js
drwxr-xr-x 1 bob bob 4.0K Jun 12 10:01 bin
-rw-rw-rw- 1 bob bob 49 Jun 15 14:34 jest.config.js`;

  // I know this doesn't work, just trying to illustrate what I'm trying to do.
    sshExec.mockReturnValue(Promise.resolve(resp));

  const received = await myCodeThatUsesSshExec(1,2,3);
  expect(received).toEqual(['Dockerfile', 'app.js', 'bin', 'jest.config.js']);

});

如何模拟ssh-exec的回调?

javascript unit-testing jestjs
1个回答
1
投票

简而言之,你的答案是 不要 模拟回调,因为那是你要测试的主题的一部分。你当前的测试没有工作,因为 ssh-exec 返回一个承诺;它接受并调用一个回调。一般来说,测试双工需要匹配它们所替换的东西的接口。

相反,使用你的模拟的 ssh-exec 来调用 真正 回调。

const sshExec = require('ssh-exec');

const myCodeThatUsesSshExec = require('./my-code');

jest.mock('ssh-exec');

test('ssh test', async () => {
    const resp = `total 268K
-rw-rw-rw- 1 bob bob 369 Jun 12 15:00 Dockerfile
-rw-rw-rw- 1 bob bob 849 Jun 12 14:46 app.js
drwxr-xr-x 1 bob bob 4.0K Jun 12 10:01 bin
-rw-rw-rw- 1 bob bob 49 Jun 15 14:34 jest.config.js`;

  // you can't await here, because it will block until the callback is invoked...
  const promise = myCodeThatUsesSshExec(1, 2, 3);

  // assert on the call to ssh-exec
  expect(sshExec).toHaveBeenCalledWith('ls -lh', '[email protected]', expect.any(Function));

  // invoke the callback, which is the third argument to the first call
  sshExec.mock.calls[0][2](null, resp);

  // assert on the result
  expect(await promise).toEqual(['Dockerfile', 'app.js', 'bin', 'jest.config.js']);
  // or you can remove async from this test case and use:
  // expect(promise).resolves.toEqual(['Dockerfile', 'app.js', 'bin', 'jest.config.js']);
});

或者,你可以自己做一个包装器 ssh-exec 更符合你的用例。

const sshPromise = (...args) => new Promise((resolve, reject) => {
  sshExec(...args, (err, stdout, stderr) => {
    if (err) {
      reject(err);
    } else if (stderr) {
      reject(stderr);
    } else {
      resolve(stdout);
    }
  });
});

现在你可以模拟这个更简单的界面,你自己的界面,你的原始测试就会像预期的那样工作。

这也简化了消耗的代码。

const myCodeThatUsesSshExec = (arg1, arg2, arg3) => sshPromise('ls -lh', '[email protected]')
  .then((stdout) => {
    // process stdout
    const results = process stdout into an array...
    return results;
  });
© www.soinside.com 2019 - 2024. All rights reserved.