вернуть читаемый макет из иглы с помощью nock — тест потока с фильтрацией twitter

#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. Я обновил вопрос тем, чего мне удалось достичь на данный момент. Сможете ли вы изменить мой последний тест на основе вашего предложения в ответе, чтобы дать мне представление о том, как именно я смогу генерировать события?