#javascript #node.js #stream #nock #needle
#javascript #node.js #поток #nock #needle
Вопрос:
Я пытаюсь уже несколько часов, и я все еще пытаюсь, как правильно протестировать мое подключение к потоку с фильтрацией 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 потока с фильтрацией twitter, который поддерживается постоянно, и это поток, в который отправляются твиты.
Во-первых, я хочу проверить, получаю ли я надлежащий поток из 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
событие.
Комментарии:
1. Я не думаю, что вы хотите «испускать» поток. Вы хотите «записать» в него. Вы должны быть в состоянии просто использовать nodejs.org/api/stream.html#stream_class_stream_writable вместо сквозного перехода, хотя это все равно должно работать. Что касается сравнения потоков, они не совпадают с потоками машинного оборудования в запросе, а nock — это конвейерные данные. Вы должны просто утверждать, что запись в макет потока приводит к получению события «данные» из needle.
2. Я обновил вопрос тем, чего мне удалось достичь на данный момент. Сможете ли вы изменить мой последний тест на основе вашего предложения в ответе, чтобы дать мне представление о том, как именно я смогу генерировать события?