Jest: Как правильно тестировать пустые функции, содержащие обещания? - PullRequest
0 голосов
/ 30 августа 2018

Я пишу приложение с React Native. Я использую Firebase Cloud Messaging для общения в реальном времени. В настоящее время я пишу модульные тесты для кода FCM, используя шутку. Проблема в том, что я изо всех сил пытаюсь заставить его работать, так как он состоит из пустых функций, которые содержат обещания. Позвольте мне дать вам код:

fcm.js:

import { Alert } from "react-native";
import firebase from "react-native-firebase";

export const checkNotificationsPermission = () => {
  firebase
    .messaging()
    .hasPermission()
    .then(enabled => {
      if (enabled) {
        // User has permissions.
      } else {
        // User doesn't have permission.
        Alert.alert(
          alertMessages.firebasePrepareForPermissionTitle,
          alertMessages.firebasePrepareForPermissionMessage,
          [{ text: buttonTexts.ok, onPress: () => requestNotificationsPermission() }]
        );
      }
    });
};

export const requestNotificationsPermission = () => {
  firebase
    .messaging()
    .requestPermission()
    .then(() => {
      // User has authorised.
    })
    .catch(() => {
      // User has rejected permissions.
      Alert.alert(
        alertMessages.firebasePrepareForPermissionTitle,
        alertMessages.firebasePermissionDeniedMessage,
        [{ text: buttonTexts.ok, onPress: () => {} }]
      );
    });
};

fcm.test.js:

import firebase from "react-native-firebase";

describe("checkNotificationsPermission", () => {
  beforeEach(() => {
    return checkNotificationsPermission();
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

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

Вот как я высмеял базу огня (__mocks__/react-native-firebase.js):

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

export default firebase;

Тест не пройден с Expected mock function to have been called one time, but it was called zero times.. Так как это не сработало, и У меня был похожий вопрос об обещаниях, на которые я получил ответ, я попытался применить то, что узнал, что привело к следующему коду.

fcm.js:

import { Alert } from "react-native";
import firebase from "react-native-firebase";

export const checkNotificationsPermission = () =>
  new Promise((resolve, reject) => {
    firebase
      .messaging()
      .hasPermission()
      .then(enabled => {
        if (enabled) {
          // User has permissions.
          resolve(true);
        } else {
          // User doesn't have permission.
          Alert.alert(
            alertMessages.firebasePrepareForPermissionTitle,
            alertMessages.firebasePrepareForPermissionMessage,
            [
              {
                text: buttonTexts.ok,
                onPress: () =>
                  requestNotificationsPermission()
                    .then(() => resolve(true))
                    .catch(() => reject(false))
              }
            ]
          );
        }
      });
  });

export const requestNotificationsPermission = () =>
  new Promise((resolve, reject) => {
    firebase
      .messaging()
      .requestPermission()
      .then(() => {
        // User has authorised.
        resolve(true);
      })
      .catch(() => {
        // User has rejected permissions.
        reject(true);
        Alert.alert(
          alertMessages.firebasePrepareForPermissionTitle,
          alertMessages.firebasePermissionDeniedMessage,
          [{ text: buttonTexts.ok, onPress: () => {} }]
        );
      });
  });

fcm.test.js:

import firebase from "react-native-firebase";

import { requestNotifcationsPermission } from "./fcm";

describe("checkNotificationsPermission", () => {
  afterEach(() => {
    jest.clearAllMocks();
  });

  it("should call firebase's hasPermission", () => {
    expect.assertions(1);
    return checkNotificationsPermission().then(() => {
      expect(firebase.messaging().requestPermission).toHaveBeenCalledTimes(1);
    });
  });
});

Но по какой-то причине эти тесты все еще не пройдены. Я эмпирически проверил и убедился, что код работает. Только юнит-тесты не пройдут.

Редактировать

Я случайно пропустил, что оба файла fcm.js также имеют следующий импорт:

import alertMessages from "../../config/constants/alertMessages";
import buttonTexts from "../../config/constants/buttonTexts";
...