如何为异步函数编写测试结构?

5

我习惯使用标准的Node.js assert库编写Mocha测试,像这样:

describe('Some module', () => {
   var result = someCall();
   it('Should <something>', () => {
      assert.ok(...);
   });
})

但现在我的调用返回一个 Promise ... 所以我想要写成:

describe('Some module', async () => {
   var result = await someCall();
   it('Should <something>', () => {
      assert.ok(...);
   });
})

但它不起作用。我的测试根本无法运行。奇怪的是,

describe('Some module', async () => {
   it('Should <something>', () => {
      var result = await someCall();
      assert.ok(...);
   });
})

这段代码本身没问题,但我想一次性调用它并运行多个测试,所以我想在it()之外进行调用。

我该如何实现呢?

不要推荐Chai库。我想使用标准的assert库。

3个回答

5

before接受一个async函数,因此您可以在测试运行之前获取result并像这样在测试中使用它:

const assert = require('assert');

const someCall = () => Promise.resolve('hi');

describe('Some module', () => {
  let result;

  before(async () => {
    result = await someCall();
  });

  it('Should <something>', () => {
    assert.equal(result, 'hi');  // Success!
  });
});

3
虽然使用起来有些不寻常,但一种方法是使用before() hook来实现您所需的功能。 before()钩子提供了在测试套件中其余测试执行之前调用功能(例如someCall())的方法。该钩子本身支持通过回调函数(例如done)执行异步功能,一旦异步功能完成即可调用该函数:
before((done) => {
  asyncCall().then(() => {
    /* Signal to the framework that async call has completed */
    done(); 
  });
});

将其与现有代码集成的一种方法可能如下:

describe("Some module", () => {
  /* Stores result of async call for subsequent verification in tests */
  var result;

  /* User before hook to run someCall() once for this suite, and
  call done() when async call has completed */
  before((done) => {
    someCall().then((resolvedValue) => {
      result = resolvedValue;
      done();
    });
  });

  it("Should <something>", () => {

    /* result variable now has resolved value ready for verification */
    console.log(result);
  });
});

希望这能有所帮助。

1
如果asyncCall返回一个Promise,则在before中不需要使用done。只需返回Promise即可。before(() => { return asyncCall().then(() => { // 在转到it之前做一些事情 }); });除此之外,我会使用before - nicholaswmin
@NikKyriakides 感谢您的反馈 :-) 我最初选择了您提到的基于 async/await 的方法,但在我的环境中似乎无法工作(尽管应该可以),而发布的解决方案却可以。您有什么想法为什么会这样? - Dacre Denny
如果您没有使用 done,则需要 返回 一个 Promise。由于 async 函数已经返回了一个 Promise,因此在 before 中简单地返回 asyncCall 就足够了。在该块中不需要使用 async/await - nicholaswmin
奇怪 - 这就是我最初所做的。明天我可能需要重新检查我的另一台工作站上的代码。再次感谢 :) - Dacre Denny

1
Mocha已经支持您想要做的事情。
Mocha的`describe`函数不是为异步工作而设计的。但是,`it`函数可以通过传递`done`回调(实际参数名可以是任何名称,如“complete”、“resolve”或“done”)、返回一个Promise或传递一个`async`函数来异步工作。
这意味着您的测试案例几乎是正确的。您只需要这样做即可:
describe('Some module', () => {
   it('Should <something>', async () => {
      var result = await someCall();
      assert.ok(...);
   });
})

如果您需要在多个it块中运行someCall()函数一次,您可以像其他答案中提到的那样,在before块中调用它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接