#typescript #promise #async-await #stream #protractor
#машинопись #обещание #асинхронное ожидание #поток #транспортир
Вопрос:
Я прочитал тестовую конфигурацию из CSV
файла с csv-parser
, который ведет себя асинхронно. Когда я оборачиваю анализатор в обещание и использую его в своем асинхронном it
тестовом примере с помощью await, данные конфигурации разрешаются… за пределами «it» это не разрешено, поскольку describe поддерживает no async
и module: commonjs
не допускает ожидания верхнего уровня. Данные конфигурации содержат тестовые данные, которые используются для выполнения тестового примера «it» в цикле с различными параметрами. Итак, мне нужен способ:
- разрешите обещание вне «it», чтобы получить данные конфигурации ИЛИ
- чтобы найти способ дождаться завершения
csv-parser
потока / канала / включения, прежде чем возвращать данные конфигурации.
export function initCountryMatrixFromCsv() {
return new Promise <Map<string, ShopFunction>>((resolve, reject) => {
const countryShopFunctions = new Map<string, ShopFunction>();
countryShopFunctions.set(ALL_FUNCTIONS, new Map<string, ShopFunction>());
const fs = require('fs');
const csv = require('csv-parser');
const parsedCsv = [];
// behaves async... returns imediately and without the promise countryShopFunctions map is not filled:
fs.createReadStream(__dirname '/country_matrix.csv')
.pipe(csv({ separator: ',' }))
.on('headers', async (headers) => {
// some header inits
}
)
.on('data', async (data) => await parsedCsv.push(data))
.on('end', async () => {
// init configuration in countryShopFunctions
});
});
describe('E2E-I18N-CMX: test country matrix', () => {
// a promise... await not alowed here
const matrix = initCountryMatrixFromCsv();
// not possible since matrix is a promise
matrix.forEach((shopFunction, roleName) = > {
it('Test ' role, async (){
// perform test with shopFunction params
// first place to resolve the promise ... but i need it outside the it
const matrix2 = await initCountryMatrixFromCsv();
});
});
});
Я попробовал несколько вариантов с обещанием и без него, но все закончилось пустой картой, когда я не использую обещание с ожиданием.
Ответ №1:
Я предполагаю, что вы используете Protractor с Jasmine (хотя на самом деле это не имеет большого значения).
Jasmine попытается разрешить тестовые примеры до initCountryMatrixFromCsv
того, как будет разрешен ваш фактический метод. Причина этого проста: он должен знать, сколько тестов существует в рамках его настройки.
Я столкнулся с той же проблемой в наших тестах, и решение состояло в том, чтобы прочитать синхронизацию CSV-файла.
Для этого я использовал пакет csv-load-sync npm, а затем прочитал файл:
import * as fs from 'fs';
import * as loader from 'csv-load-sync';
import * as path from 'path';
readTestDataCsvSync() {
const filePath = path.join(__dirname, 'TestData.csv');
try {
if (fs.existsSync(filePath)) {
return loader(path.join(__dirname, 'TestData.csv'));
}
}
catch (err) {
throw new Error(`Couldn't load the test cases CSV file: ${err}`);
}
}
Теперь вы можете просто выполнять свои тесты, как и раньше:
describe('E2E-I18N-CMX: test country matrix', () => {
const matrix = readTestDataCsvSync();
matrix.forEach((shopFunction, roleName) = > {
it('Test ' role, async (){
// your test
});
});
});
Ответ №2:
Поместите функцию инициализации в блок beforeAll /beforeEach . Затем матрица доступна в каждом ит
describe('your test', () => {
let matrix2;
beforeAll(async () => {
matrix2 = await initCountryMatrixFromCsv();
});
it('my test', () => {
expect(matrix2).toBeTruthy(); // do more verifications ...
});
});
Также убедитесь resolve
, что обещание в функции. Я думаю, вы хотите, чтобы это разрешилось в on (‘end’)
Комментарии:
1. да, я разрешаю обещание в on (‘end’). Я также уже пробовал beforeAll / beforeEach и внутри «it» он разрешен, но не за пределами «it». Поэтому я не могу использовать matrix.forEach вне it.