вернуть читаемый макет из иглы с помощью nock - тест отфильтрованного потока Twitter
Я пытаюсь в течение нескольких часов и все еще пытаюсь правильно проверить свое соединение с потоком с фильтром Twitter.
Вот как выглядит мой класс, который я хочу протестировать:
import { injectable } from 'inversify';
import { ReadableStream } from 'needle';
import needle from 'needle';
@injectable()
export class TwitterStreamAdapter {
public stream: ReadableStream | undefined;
public startStream = (): void => {
const streamUrl = process.env.TWITTER_STREAM_URL as string;
this.stream = needle.get(streamUrl, { // <<----- I WANT TO TEST THIS
headers: { Authorization: `Bearer ${process.env.TWITTER_BEARER_TOKEN}` },
});
this.stream
.on('data', (data) => {
try {
console.log(JSON.parse(data));
} catch (e) {
// Keep alive signal received. Do nothing.
}
})
};
}
Короче говоря, здесь я создаю соединение с api отфильтрованного потока твиттера, который постоянно поддерживается и является потоком, в который отправляются твиты.
Во-первых, я хочу проверить, получаю ли я правильный поток от needle.get
хотя вы, вероятно, можете возразить, что я пытаюсь протестировать библиотеку вместо своей реализации.
Потерпите минутку и посмотрите тест ниже:
beforeEach(() => (twitterStreamAdapter = new TwitterStreamAdapter()));
it('connects to filtered stream and returns stream', (done) => {
const host = 'https://api.twitter.com';
const path = '/2/tweets/search/stream';
const mockedStream = new PassThrough(); // <<---- I want to be able to emit with this stream
const scope = nock(host, {
reqheaders: {
authorization: `Bearer ${process.env.TWITTER_BEARER_TOKEN}`,
},
})
.get(path)
.delay(2000)
.reply(200, () => mockedStream);
twitterStreamAdapter.startStream();
twitterStreamAdapter.stream!.emit('data', { message: 'hello world'}); // <<--- this works, but I don't want to use the prop of the instance to emit
mockedStream.emit('data', 'hello world 2'); // <<---- this doesn't work, I'd like to use mockedStream to emit
expect(twitterStreamAdapter.stream).toEqual(mockedStream); // <<--- this expectation fails
});
Здесь, в тесте, я хотел бы создать mockedStream
, и я бы хотел, чтобы этот поток возвращался из needle.get
. Таким образом, у меня будет больше контроля над своими тестами. Во-первых, мне бы не пришлось делать свойство моего классаthis.stream
общественность.
В тесте Вы видите, что я делаю twitterStreamAdapter.stream.emit
который работает и генерирует событие, которое передается обратному вызову this.stream.on('data' ...)
что вы можете увидеть в реализации метода классов.
Также в тесте есть такая строка:
expect(twitterStreamAdapter.stream).toEqual(mockedStream);
Как на самом деле я могу проверить, возвращается ли правильный поток (фиктивный) из needle.get
.
Честно говоря, я немного запутался во всем этом, я впервые пытаюсь протестировать запрос, который действительно остается активным и возвращает потоки данных.
Любая помощь очень ценится!
ИЗМЕНИТЬ ---- на основе того, что я исследовал до сих пор -----, но все еще есть проблемы:
Пока что я переписал свой текущий тестовый код так:
it('handles stream data event', async (done) => {
const mockedResponse = { message: 'hello from nock' };
nock(host, {
reqheaders: {
authorization: `Bearer ${process.env.TWITTER_BEARER_TOKEN}`,
},
})
.get(path)
.reply(200, () => mockedResponse);
twitterStreamAdapter.startStream();
const stream: ReadableStream | undefined = twitterStreamAdapter.stream;
jest.spyOn(JSON, 'parse');
stream!.on('data', () => {
expect(JSON.parse).toHaveBeenCalledWith({ message: 'hello from nock' });
done();
});
});
Здесь я успешно получаю data
событие запущено, и тест работает. Проблема в том, что я пытаюсь запустить (испустить) error
событие.
Я старался:
nock(...).get(path).replyWithError({code: 'ETIMEDOUT'});
а также:
nock(...).get(path).reply(500);
И он не излучает error
событие.