Как правильно смоделировать модуль React Native, который использует нативный код? - PullRequest
0 голосов
/ 15 октября 2018

Я создаю приложение React Native с помощью TypeScript.Я использую response-native-firebase для своих уведомлений.Кроме того, я использую Jest и Enzyme для своих модульных тестов.

У меня есть следующая функция-обертка для проверки прав пользователей:

export const checkPermissions = (): Promise<boolean> =>
  new Promise((resolve, reject) => {
    firebase
      .messaging()
      .hasPermission()
      .then(enabled => {
        if (enabled) {
          resolve(enabled);
        } else {
          firebase
            .messaging()
            .requestPermission()
            .then(resolve)
            .catch(reject);
        }
      });
  });

Теперь я хочу проверить, вызывается ли функция

Вот тест, который я написал:

import * as firebase from "react-native-firebase";
import { checkPermissions } from "./notificationHelpers";

jest.mock("react-native-firebase");

describe("checkPermissions", () => {
  beforeEach(async done => {
    jest.resetAllMocks();
    await checkPermissions();
    done();
  });

  it("should call firebase.messaging().hasPermission()", () => {
    expect(firebase.messaging().hasPermission).toHaveBeenCalledTimes(1);
  });
});

Это выдает ошибку:

 FAIL  app/services/utils/core/notificationHelpers/notificationHelpers.test.ts
  ● Test suite failed to run

    RNFirebase core module was not found natively on iOS, ensure you have correctly included the RNFirebase pod in your projects `Podfile` and have run `podinstall`.

     See http://invertase.link/ios for the ios setup guide.

      Error: RNFirebase core module was not found natively on iOS, ensure you have correctly included the RNFirebase pod in your projects `Podfile` and haverun `pod install`.

Так что мне кажется, что модули, которые используют собственный код, могут 'Это просто с помощью авто-насмешек.

Так что я попытался сделать это вручную.Внутри папки __mocks__, которая находится в моем корневом проекте рядом с node_modules, я создал файл с именем react-native-firebase.ts, который выглядит следующим образом:

const firebase = {
  messaging: jest.fn(() => ({
    hasPermission: jest.fn(() => new Promise(resolve => resolve(true)))
  }))
};

export default firebase;

Но этот код также не работает, потому что firebase.messagingякобы не определено.

Как можно было бы проверить этот материал?10

РЕДАКТИРОВАТЬ: Ничего себе, насмешка, кажется, полностью сломан в RN 0.57.x : (

1 Ответ

0 голосов
/ 14 апреля 2019

Вот способ проверить код, который зависит от react-native-firebase

Создать ручной макет, просто добавив пустой файл в папку __mocks__/react-native-firebase.js, mocks , которая должна находиться втот же уровень, что и node_modules, как объяснено в jest docs конкретно Модули Mocking Node section.

С этим издевательским руководством вы избежите ошибки

    RNFirebase core module was not found natively on iOS, ensure you have correctly included the RNFirebase pod in your projects `Podfile` and have run `pod install`.

Тогда вам не нужно jest.mock("react-native-firebase");, также вам не нужно проверять expect(firebase.messaging().hasPermission).toHaveBeenCalledTimes(1);

Чтовместо этого вы можете изолировать код, который зависит от react-native-firebase, от небольших функций, а затем шпионить за теми, кто добавляет известные результаты.

Например, эта функция verifyPhone, которая зависит от response-native-firebase.

// ./lib/verifyPhoneNumber.ts
import firebase from "react-native-firebase";

const verifyPhoneNumber = (phoneNumber: string) => {
  return new Promise((resolve, reject) => {
    firebase
      .auth()
      .verifyPhoneNumber(phoneNumber)
      .on("state_changed", phoneAuthSnapshot => {
        resolve(phoneAuthSnapshot.state);
      });
  });
};

export default verifyPhoneNumber;

Для проверки кода, который зависит от функции verifyPhoneNumber, вы следите за ней и заменяете ее реализацию следующим образом.

jest.mock("react-native-firebase");

import { signInWithPhone } from "../actions";
import verifyPhoneNumberEpic from "./verifyPhoneNumberEpic";
import { ActionsObservable } from "redux-observable";
// Note "import * as" is needed to use jest.spyOn(verifyPhoneNumber, "default");
import * as verifyPhoneNumber from "./lib/verifyPhoneNumber";

describe("Epic: verifyPhoneNumberEpic", () => {
  test('On Request "[Auth] Verify Phone Number Request" executes the promise', done => {
    // Create the spy
    const verifyPhoneNumberMock = jest.spyOn(verifyPhoneNumber, "default");
    // For this test I simulate the promise resolves with CODE_SENT
    verifyPhoneNumberMock.mockImplementation(async () => "CODE_SENT");
    // the rest of the code is very specific for testing Epics (redux-observable)
    // But all you need to know is that internally my epic verifyPhoneNumberEpic
    // calls verifyPhoneNumber but the implication will be replaced with the spy

    const requestAction = signInWithPhone.request({
      phoneNumber: "+40111222333"
    });
    const action$ = ActionsObservable.of(requestAction);

    verifyPhoneNumberEpic(action$, null, null).subscribe((action: any) => {
      expect(action.payload.code).toBe("CODE_SENT");
      expect(action.type).toBe(signInWithPhone.success.toString());
      done();
    });
  });

Надеюсь, это поможет!

...