private-key.json이 없어서 FirebaseMessaging 빈을 생성하지 못하는 트러블 슈팅 #371
kwonyj1022
started this conversation in
참고자료
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
FCM으로 알림을 전송하기 위해서는
FirebaseMessaging
객체가 필요하고, 아래와 같은 설정이 필요하다.yml 파일에 명시한 경로에 반드시
private-key.json
파일이 있고 유효한 데이터(파이어베이스에서 받은 진짜 파일)가 존재해야 애플리케이션을 실행하고, 테스트도 실행시킬 수 있다.문제는 이
private-key.json
은 공유되면 안 되기 때문에 github에 올릴 수 없다는 것이다.그래서 올리더라도 안의 데이터는 삭제하고 올려야 한다.
하지만, 파일의 내용이 유효하지 않으면 빈 등록 과정에서 예외가 발생하기 때문에 어플리케이션 실행도 안 되고,
@SpringBootTest
를 사용하는 모든 테스트는 실패하게 된다.이를 해결하기 위해 처음에는
@TestConfiguration
을 통해 테스트 환경에서는FirebaseMessaging
을 mock 객체로 등록하도록 하는 방법을 시도했다.그래도 여전히 문제는 해결되지 않았다. 정확한 이유는 모르겠지만..(아시는 분 댓글 바랍니다.)
테스트 실행 시에도 애플리케이션을 실행할 때 호출되는
FcmConfiguration이
실행되는데,private-key.json
으로부터FirebaseMessaging
인스턴스를 만들 수 없었기 때문이다. (보안을 위해private-key.json
의 내용을 비워뒀기 때문)그래서 어차피 프로덕션 코드에 있는
FcmConfiguration
이 실행된다면FcmConfiguration
에서FirebaseMessaging
빈 등록을 제어할 수 있도록 설정해주는 방법을 생각했다.application-local.yml
에 enabled 옵션을 추가하고FcmConfiguration
에서 enabled 값에 따라 분기처리를 하였다.여기서 문제는, 프로덕션 코드에서는
Mockito.mock()
을 사용할 수 없었다는 것이다.그래서
FirebaseMessaging
인스턴스를 가짜로 만들어주도록 하였다.맨 위에 제시된 기존
FcmConfiguration
클래스에서FirebaseMessaging
인스턴스를 만들어주는 부분의 코드는 아래와 같다.private-key.json
을 통해 읽은 refreshToken으로 Credentials를 설정해서FirebaseOptions
를 만들고, 해당 옵션을 통해 FirebaseApp을 초기화하고,FirebaseMessaging
인스턴스를 얻는 과정이다.이 일련의 과정을 어떻게 모킹할 수 있을까 찾아보다가 firebase 소스코드를 깃허브에서 찾을 수 있었다.
firebase의 FirebaseMessagingTest.java에서 테스트용 FirebaseOptions를 만드는 부분의 코드를 확인할 수 있었다.
해당 코드를
FcmConfiguration
클래스에 복사해보니MockGoogleCredentials
클래스가 없다는 에러가 나타났다.그래서 다시 링크로 돌아가서
MockGoogleCredentials
클래스의 위치를 import문을 통해 확인할 수 있었고, 해당 위치로 가서MockGoogleCredentials.java
의 코드를 확인할 수 있었다.해당 코드를 복사해서
MockGoogleCredentials
클래스를 만들어주었더니FcmConfiguration의
컴파일에러가 사라졌다.따라서 기존에
FirebaseMessaging
인스턴스를 만들어주는 부분의 코드와 비슷한 방식으로FirebaseMessaging
을 생성할 수 있었다.가짜
FirebaseMessaging
객체를 만드는 것까지는 성공한 듯하다.테스트를 돌려보니 여전히 실패한다.
실패 원인은 아래와 같다.
Caused by: java.lang.IllegalStateException: FirebaseApp name [DEFAULT] already exists!
예외가 발생하는 위치를 가보니 if문 안의 return 문에서
FirebaseApp.initializeApp(TEST_OPTIONS)
에서FirebaseApp
인스턴스가 이미 만들어져 있는데 테스트 하나 실행할 때마다 또 만들어서 생긴 오류이다. 실제로 테스트를 한 개만 돌렸을 때는 성공하는데, 전체 테스트를 한 번에 돌리면 실패한다.그래서
FirebaseApp.initializeApp(TEST_OPTIONS)
를 static으로 빼주었다.드디어 모든 테스트가 통과한다!
Beta Was this translation helpful? Give feedback.
All reactions