Использование оператора задержки RxJS в тестах Ava
Я являюсь автором программы на JavaScript, которую необходимо выполнить на основе ряда тестов. Я обнаружил, что каждый из этих тестов имеет одинаковый формат, и поэтому целесообразно генерировать тесты с использованием заводской функции.
Заводская функция называется testFactory и показана в приведенном ниже коде. Он вызывается с массивом данных, который после добавления логики моего приложения будет инструктировать фабрику о том, как построить конкретный тест. Функция фабрики также отвечает за выполнение тестов.
Я выбрал RxJS для достижения двухсекундной задержки, если строка "задержка" включена в данные, передаваемые на завод. (Моя предыдущая попытка реализации использовала обещания, но мне не удалось заставить этот подход работать.) Как вы можете видеть, это достигается с помощью оператора задержки Rx.
Ava была выбрана потому, что она имеет репутацию работы с RxJS. Как видите, я делаю звонки на Rx Subject из подписки на мою наблюдаемую.
В моем действительном коде приложения эта подписка делает вызовы конечному автомату, который реализует логику моего приложения, и данные из конечного автомата передаются в субъект через вызовы следующего метода субъекта в методе обратного вызова на конечном автомате. Вот почему я не могу просто подключить свою наблюдаемую непосредственно к методу тестирования Ava, а вместо этого должен пройти через предмет. Предмет был выбран вместо наблюдаемого для способности субъекта позволять делать вызовы его следующим и завершенным методам вне его определения.
Я удалил логику приложения из приведенного ниже кода, чтобы не путать проблему с этими деталями. Проблема возникает, когда строка 'delay' удаляется из массива данных. Когда этот код выполняется с данными, которые не содержат задержки, тест не проходит:
const data = [
{ r: 'c' },
{ l: 'c' },
{ l: 'n' },
{ l: 'c' }
];
Это терпит неудачу с: Test finished without running any assertions.
Как я могу получить это прохождение, когда нет "задержки" в массиве данных? Почему происходит сбой, когда в массиве данных нет "задержки"? Спасибо.
const ava = require('ava');
const { test } = ava;
const Rx = require('rxjs/Rx');
const { Observable, Subject } = Rx;
const data = [
{ r: 'c' },
{ l: 'c' },
{ l: 'n' },
'delay',
{ l: 'c' }
];
const testFactory = (data) => {
let subject = new Subject();
// This code adds a delay property to each item which passes through, adding a
// delay value based on a cumulative delay value maintained by the scan
// operator. Items which are simply delays are marked with a 'skip' property
// in the scan and skipped in the flatMap. Once the delay has been performed
// by the delay operator, the added delay property is deleted. If there is a
// simpler way in Rx to achieve this functionality, I'm open to suggestions
// on refactoring this code. :-)
const source = Observable.from(data)
.scan((acc, val) => {
if (val === 'delay') {
return { skip: true, delay: acc.delay + 2000 };
}
return Object.assign(val, { delay: acc.delay });
}, { delay: 0 })
.flatMap((e) => {
if (e.skip) {
return Observable.empty();
} else {
return Observable.of(e)
.delay(e.delay)
.map(e => { delete e.delay; return e; });
}
});
// This is the subscribe block which in my application called my state
// machine. Since the state machine has been removed, the Subject is called
// directly, instead of calling it from the callback tot the state machine.
// Either way, the same problem exists.
source
.subscribe({
next: e => {
subject.next(e);
},
complete: () => {
subject.complete();
}
});
// This test always passes. When the 'delay' is removed, the failure would
// indicate to me that its never called.
test('', t => {
// t.plan(1);
return subject
.map((n) => {
t.true(true);
});
});
};
testFactory(data);
Примечание: Интересно, что когда импорт Ava удаляется вместе со строкой ниже, в которой импортируется тестовая функция Ava, а вызов тестовой функции заменяется обычной подпиской RxJS на тему, код работает как с задержкой, так и без нее. строка в структуре данных:
// test('', t => {
// // t.plan(1);
// return subject
// .map((n) => {
// t.true(true);
// });
// });
subject.subscribe((v) => {
console.log(JSON.stringify(v));
});
Означает ли это, что проблема с моим использованием Ava?
1 ответ
Я не очень знаком с RxJS, наблюдаемыми или предметами, но есть ключ в Test finished without running any assertions.
Тесты AVA могут быть синхронными или асинхронными, когда вы возвращаете наблюдаемое, обещание или использование test.cb(t => t.end())
, AVA также не проходит тесты, если до его завершения не было выполнено никаких утверждений.
В вашем случае, похоже, AVA определила, что ваш тест является синхронным. Вы должны убедиться, что он асинхронный, и заканчивать его только тогда, когда данные полностью используются.