typescript - Cum să simulezi furnizorii de autentificare Firebase, cum ar fi FacebookAuthProvider?


Încerc să fac mock la obiectul firebase.auth din react-native-firebase astfel încât să returneze un credential codului testat, astfel încât să pot testa metoda mea.

Am următorul cod de testat:

public async FacebookSignIn(): Promise<void> {
    try {
      const result = await LoginManager.logInWithReadPermissions(['public_profile', 'email']);

      if (result.isCancelled) {
        throw new Error('User cancelled request');

      }

      const data = await AccessToken.getCurrentAccessToken();

      if (!data) {
        throw new Error('Something went wrong obtaining the users access token');
      }

      const credential = firebase.auth.FacebookAuthProvider.credential(data.accessToken);
      await firebase.auth().signInWithCredential(credential);
    }
    catch (error) {
      console.error(error);
    }
  }

Vreau să mă asigur că la sfârșitul funcției, CUT-ul meu apelează signInWithCredential, așa că am un caz de test ca acesta; func este global : jest.fn()

describe('FacebookSignIn', () => {
    it('should sign in user with facebook credentials', async () => {
      await service.FacebookSignIn();
      expect(func).toHaveBeenCalled();
    })
  })

Totuși, cu următorul mock primesc eroarea TypeError: Cannot read property 'credential' of undefined:

jest.mock('react-native-firebase', () => {
  return {
    auth: () => {
      return {
        currentUser: null,
        signOut: func,
        signInAnonymously: func,
        signInWithEmailAndPassword: func,
        signInWithCredential: func,
        FacebookAuthProvider: jest.fn(() => {
          return {
            credential: jest.fn(() => {
              return {
                provider: 'dummy',
                token: '1234',
                secret: '5678'
              }
            })
          }
        })
      }
    }
  }
});

Am verificat tipul pentru firebase.auth și poate returna asta:

type AuthModule = {
    (): RNFirebase.auth.Auth;
    nativeModuleExists: boolean;
} & RNFirebase.auth.AuthStatics

care pentru mine pare că se face mock la metodele signIn corect, dar metodele AuthStatics nu sunt mock-uite. AuthStatics este definit astfel:

interface AuthStatics {
        EmailAuthProvider: EmailAuthProvider;
        PhoneAuthProvider: AuthProvider;
        GoogleAuthProvider: AuthProvider;
        GithubAuthProvider: AuthProvider;
        OAuthProvider: AuthProvider;
        TwitterAuthProvider: AuthProvider;
        FacebookAuthProvider: AuthProvider;
        PhoneAuthState: {
          CODE_SENT: string;
          AUTO_VERIFY_TIMEOUT: string;
          AUTO_VERIFIED: string;
          ERROR: string;
        };
      }

Cum pot să fac un mock la proprietatea FacebookAuthProvider și să evit să fie nedefinită pentru credential?

Răspuns #1

Deși întrebarea ta este puțin mai veche, am dat peste aceeași provocare și am reușit să o rezolv în felul următor:

Creează o simulare implicită a modulului de autentificare în rădăcina proiectului tău

// file: __mocks__/@react-native-firebase/auth/index.js

const auth = jest.fn().mockReturnValue({
  onUserChanged: jest.fn().mockReturnValue(() => {}),
  createUserWithEmailAndPassword: jest.fn(),
  signInWithCredential: jest.fn(),
  // more functions from the module you want to use in your tests
});

auth.FacebookAuthProvider = {
  credential: jest.fn(),
};

export default auth;

Apoi, în fișierul tău de test

describe('auth', () => {
  let authMock: jest.Mocked<ReturnType<typeof firebaseAuth>>;
  let facebookAuthProviderMock: jest.Mocked<FirebaseAuthTypes.AuthProvider>;

  beforeEach(() => {
    authMock = firebaseAuth() as jest.Mocked<ReturnType<typeof firebaseAuth>>;
    facebookAuthProviderMock = firebaseAuth.FaceAuthProviderMock as jest.Mocked<FirebaseAuthTypes.AuthProvider>;
  });

  it('your test', () => {
  // given
    authMock.signInWithCredential.mockResolvedValue({});
    facebookAuthProviderMock.credential.mockReturnValue({});

  // ...

  // then
  expect(authMock.signInWithCredential).toHaveBeenCalledWith({});
  })
})