问题
I have simplified the example to be able to explain it well. I have an array which I want to iterate on. For each element of the array I want to execute a test with async/await functions, so I have this code:
const chai = require('chai');
const expect = chai.expect;
describe('Each film', async() => {
await Promise.all([1, 2, 3].map(async(n) => {
await new Promise(resolve => setTimeout(() => resolve(), 1000));
console.log('N:', n);
it('test', async() => {
expect(true).to.be.true;
});
}));
});
Executing this results in the following output:
0 passing (1ms)
N: 1
N: 2
N: 3
However, if I don't use async/await it is executed as I would expect, so it generates three tests that are resolved correctly.
What could be happening here?
UPDATE
I finally discovered that setTimeout can be used to load data asynchronously and then generate tests dinamically. This is the explanation from mocha page:
If you need to perform asynchronous operations before any of your suites are run, you may delay the root suite. Run mocha with the --delay flag. This will attach a special callback function, run(), to the global context:
So I finally wrote the code this way:
const chai = require('chai');
const expect = chai.expect;
setTimeout(async() => {
await Promise.all([1, 2, 3].map(async(n) => {
describe(`Element number ${n}`, () => {
it('test', async() => {
await new Promise(resolve => setTimeout(() => resolve(), 1000));
expect(true).to.be.true;
});
});
}));
run();
}, 500);
which generates the following output:
➜ node_modules/.bin/mocha --delay test.js
Element number 1
✓ test (1005ms)
Element number 2
✓ test (1001ms)
Element number 3
✓ test (1002ms)
3 passing (3s)
回答1:
Mocha does not support asynchronous describe
functions. You can generate tests dynamically, as described here, but that generation must still be synchronous.
Any tests that aren't created synchronously won't be picked up by the runner. Hence the 0 passing
line at the top of your output. Mocha has decided there are no tests well before your promise resolves.
This isn't to say testing your stuff is impossible, just that you need to rethink how you're using Mocha to test it. The following, for example, would be similar to loading all of your things up front and making an assertion on each one in various tests:
const chai = require('chai');
const expect = chai.expect;
describe('Each item', () => {
let items;
before(async () => {
items = [];
await Promise.all([1, 2, 3].map(async(n) => {
await new Promise(resolve => setTimeout(() => resolve(), 1000));
items.push(n);
}));
})
it('is a number', () => {
for (item of items) {
expect(item).to.be.a('number');
}
});
it('is an integer', () => {
for (item of items) {
expect(item % 1).to.equal(0)
}
});
it('is between 1 and 3', () => {
for (item of items) {
expect(item).to.be.within(1, 3)
}
});
});
Unfortunately you won't be able to make a fully separate test displaying in your output for each item. If you want this, you may check out another test runner. I don't really have enough experience with others to say whether or not any of them support this. I'd be surprised if they do, though, since it's quite unusual.
来源:https://stackoverflow.com/questions/51859356/mocha-testing-inside-async-callbacks