package rxfirebase2.auth; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseUser; import com.google.firebase.auth.ProviderQueryResult; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; import io.reactivex.functions.Predicate; import io.reactivex.observers.TestObserver; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class RxFirebaseAuthTest { @Mock FirebaseAuth mockFirebaseAuth; @Mock AuthCredential mockAuthCredential; @Mock AuthResult mockAuthResult; @Mock Task<AuthResult> mockAuthResultTask; @Mock Task<Void> mockSendPasswordResetEmailTask; @Mock Task<ProviderQueryResult> mockFetchProvidersTask; @Mock FirebaseUser mockFirebaseUser; private ArgumentCaptor<OnCompleteListener> onComplete; private ArgumentCaptor<FirebaseAuth.AuthStateListener> authStateChange; @Before public void setup() { MockitoAnnotations.initMocks(this); onComplete = ArgumentCaptor.forClass(OnCompleteListener.class); authStateChange = ArgumentCaptor.forClass(FirebaseAuth.AuthStateListener.class); } @Test public void testAuthStateChanges() { TestObserver<FirebaseAuth> obs = TestObserver.create(); RxFirebaseAuth.changes(mockFirebaseAuth) .subscribe(obs); callOnAuthStateChanged(); obs.assertNotComplete(); obs.assertValueCount(1); obs.dispose(); callOnAuthStateChanged(); // Assert no more values are emitted obs.assertValueCount(1); } @Test public void testCreateUserWithEmailAndPassword() { when(mockFirebaseUser.getEmail()) .thenReturn("[email protected]"); mockSuccessfulAuthResult(); when(mockFirebaseAuth.createUserWithEmailAndPassword("[email protected]", "password")) .thenReturn(mockAuthResultTask); TestObserver<FirebaseUser> obs = TestObserver.create(); RxFirebaseAuth .createUserWithEmailAndPassword(mockFirebaseAuth, "[email protected]", "password") .subscribe(obs); callOnComplete(mockAuthResultTask); obs.dispose(); // Ensure no more values are emitted after unsubscribe callOnComplete(mockAuthResultTask); obs.assertComplete(); obs.assertValue(new Predicate<FirebaseUser>() { @Override public boolean test(FirebaseUser firebaseUser) throws Exception { return "[email protected]".equals(firebaseUser.getEmail()); } }); } @Test public void testCreateUserWithEmailAndPassword_NotSuccessful() { when(mockFirebaseUser.getEmail()) .thenReturn("[email protected]"); mockNotSuccessfulResult(new IllegalStateException()); when(mockFirebaseAuth.createUserWithEmailAndPassword("[email protected]", "password")) .thenReturn(mockAuthResultTask); TestObserver<FirebaseUser> obs = TestObserver.create(); RxFirebaseAuth .createUserWithEmailAndPassword(mockFirebaseAuth, "[email protected]", "password") .subscribe(obs); callOnComplete(mockAuthResultTask); obs.dispose(); // Ensure no more values are emitted after unsubscribe callOnComplete(mockAuthResultTask); obs.assertError(IllegalStateException.class); obs.assertNoValues(); } @Test public void testFetchProvidersForEmail() { when(mockFirebaseAuth.fetchProvidersForEmail("[email protected]")) .thenReturn(mockFetchProvidersTask); mockSuccessfulFetchProvidersResult(); when(mockFirebaseAuth.fetchProvidersForEmail("[email protected]")) .thenReturn(mockFetchProvidersTask); TestObserver<List<String>> obs = TestObserver.create(); RxFirebaseAuth .fetchProvidersForEmail(mockFirebaseAuth, "[email protected]") .subscribe(obs); callOnComplete(mockFetchProvidersTask); obs.dispose(); // Ensure no more values are emitted after unsubscribe callOnComplete(mockFetchProvidersTask); obs.assertComplete(); obs.assertValueCount(1); } @Test public void testFetchProvidersForEmail_NotSuccessful() { when(mockFirebaseAuth.fetchProvidersForEmail("[email protected]")) .thenReturn(mockFetchProvidersTask); mockNotSuccessfulFetchProvidersResult(new IllegalStateException()); when(mockFirebaseAuth.fetchProvidersForEmail("[email protected]")) .thenReturn(mockFetchProvidersTask); TestObserver<List<String>> obs = TestObserver.create(); RxFirebaseAuth .fetchProvidersForEmail(mockFirebaseAuth, "[email protected]") .subscribe(obs); callOnComplete(mockFetchProvidersTask); obs.dispose(); // Ensure no more values are emitted after unsubscribe callOnComplete(mockFetchProvidersTask); obs.assertError(IllegalStateException.class); obs.assertNoValues(); } @Test public void testGetCurrentUser_notSignedIn() { when(mockFirebaseAuth.getCurrentUser()) .thenReturn(null); TestObserver<FirebaseUser> obs = TestObserver.create(); RxFirebaseAuth.getCurrentUser(mockFirebaseAuth) .subscribe(obs); verify(mockFirebaseAuth) .getCurrentUser(); obs.dispose(); obs.assertComplete(); obs.assertNoValues(); } @Test public void testGetCurrentUser_signedIn() { when(mockFirebaseUser.getDisplayName()) .thenReturn("John Doe"); when(mockFirebaseAuth.getCurrentUser()) .thenReturn(mockFirebaseUser); TestObserver<FirebaseUser> obs = TestObserver.create(); RxFirebaseAuth.getCurrentUser(mockFirebaseAuth) .subscribe(obs); verify(mockFirebaseAuth) .getCurrentUser(); obs.dispose(); obs.assertComplete(); obs.assertValueCount(1); obs.assertValue(new Predicate<FirebaseUser>() { @Override public boolean test(FirebaseUser user) throws Exception { return "John Doe".equals(user.getDisplayName()); } }); } @Test public void testSendPasswordResetEmail() { when(mockFirebaseAuth.sendPasswordResetEmail("email")) .thenReturn(mockSendPasswordResetEmailTask); mockSuccessfulSendPasswordResetEmailResult(); TestObserver obs = TestObserver.create(); RxFirebaseAuth .sendPasswordResetEmail(mockFirebaseAuth, "email") .subscribe(obs); callOnComplete(mockSendPasswordResetEmailTask); obs.dispose(); verify(mockFirebaseAuth) .sendPasswordResetEmail("email"); obs.assertNoErrors(); obs.assertComplete(); } @Test public void testSendPasswordResetEmail_NotSuccessful() { when(mockFirebaseAuth.sendPasswordResetEmail("email")) .thenReturn(mockSendPasswordResetEmailTask); mockNotSuccessfulSendPasswordResetEmailResult(new IllegalStateException()); TestObserver obs = TestObserver.create(); RxFirebaseAuth .sendPasswordResetEmail(mockFirebaseAuth, "email") .subscribe(obs); callOnComplete(mockSendPasswordResetEmailTask); obs.dispose(); verify(mockFirebaseAuth) .sendPasswordResetEmail("email"); obs.assertError(IllegalStateException.class); } @Test public void testSignInAnonymous() { when(mockFirebaseUser.isAnonymous()) .thenReturn(true); mockSuccessfulAuthResult(); when(mockFirebaseAuth.signInAnonymously()) .thenReturn(mockAuthResultTask); TestObserver<FirebaseUser> obs = TestObserver.create(); RxFirebaseAuth.signInAnonymous(mockFirebaseAuth) .subscribe(obs); callOnComplete(mockAuthResultTask); obs.dispose(); // Ensure no more values are emitted after unsubscribe callOnComplete(mockAuthResultTask); obs.assertNoErrors(); obs.assertValue(new Predicate<FirebaseUser>() { @Override public boolean test(FirebaseUser firebaseUser) throws Exception { return firebaseUser.isAnonymous(); } }); } @Test public void testSignInAnonymous_NotSuccessful() { mockNotSuccessfulResult(new IllegalStateException()); when(mockFirebaseAuth.signInAnonymously()) .thenReturn(mockAuthResultTask); TestObserver<FirebaseUser> obs = TestObserver.create(); RxFirebaseAuth.signInAnonymous(mockFirebaseAuth) .subscribe(obs); callOnComplete(mockAuthResultTask); obs.dispose(); // Ensure no more values are emitted after unsubscribe callOnComplete(mockAuthResultTask); obs.assertError(IllegalStateException.class); obs.assertNoValues(); } @Test public void testSignInWithCredential() { mockSuccessfulAuthResult(); when(mockFirebaseAuth.signInWithCredential(mockAuthCredential)) .thenReturn(mockAuthResultTask); TestObserver<FirebaseUser> obs = TestObserver.create(); RxFirebaseAuth .signInWithCredential(mockFirebaseAuth, mockAuthCredential) .subscribe(obs); callOnComplete(mockAuthResultTask); obs.dispose(); // Ensure no more values are emitted after unsubscribe callOnComplete(mockAuthResultTask); obs.assertComplete(); obs.assertValueCount(1); } @Test public void testSignInWithCredential_NotSuccessful() { mockNotSuccessfulResult(new IllegalStateException()); when(mockFirebaseAuth.signInWithCredential(mockAuthCredential)) .thenReturn(mockAuthResultTask); TestObserver<FirebaseUser> obs = TestObserver.create(); RxFirebaseAuth .signInWithCredential(mockFirebaseAuth, mockAuthCredential) .subscribe(obs); callOnComplete(mockAuthResultTask); obs.dispose(); // Ensure no more values are emitted after unsubscribe callOnComplete(mockAuthResultTask); obs.assertError(IllegalStateException.class); obs.assertNoValues(); } @Test public void testSignInWithCustomToken() { mockSuccessfulAuthResult(); when(mockFirebaseAuth.signInWithCustomToken("custom_token")) .thenReturn(mockAuthResultTask); TestObserver<FirebaseUser> obs = TestObserver.create(); RxFirebaseAuth .signInWithCustomToken(mockFirebaseAuth, "custom_token") .subscribe(obs); callOnComplete(mockAuthResultTask); obs.dispose(); // Ensure no more values are emitted after unsubscribe callOnComplete(mockAuthResultTask); obs.assertComplete(); obs.assertValueCount(1); } @Test public void testSignInWithCustomToken_NotSuccessful() { mockNotSuccessfulResult(new IllegalStateException()); when(mockFirebaseAuth.signInWithCustomToken("custom_token")) .thenReturn(mockAuthResultTask); TestObserver<FirebaseUser> obs = TestObserver.create(); RxFirebaseAuth .signInWithCustomToken(mockFirebaseAuth, "custom_token") .subscribe(obs); callOnComplete(mockAuthResultTask); obs.dispose(); // Ensure no more values are emitted after unsubscribe callOnComplete(mockAuthResultTask); obs.assertError(IllegalStateException.class); obs.assertNoValues(); } @Test public void testSignInWithEmailAndPassword() { mockSuccessfulAuthResult(); when(mockFirebaseAuth.signInWithEmailAndPassword("email", "password")) .thenReturn(mockAuthResultTask); TestObserver<FirebaseUser> obs = TestObserver.create(); RxFirebaseAuth .signInWithEmailAndPassword(mockFirebaseAuth, "email", "password") .subscribe(obs); callOnComplete(mockAuthResultTask); obs.dispose(); // Ensure no more values are emitted after unsubscribe callOnComplete(mockAuthResultTask); obs.assertNoErrors(); obs.assertComplete(); obs.assertValueCount(1); } @Test public void testSignInWithEmailAndPassword_NotSuccessful() { mockNotSuccessfulResult(new IllegalStateException()); when(mockFirebaseAuth.signInWithEmailAndPassword("email", "password")) .thenReturn(mockAuthResultTask); TestObserver<FirebaseUser> obs = TestObserver.create(); RxFirebaseAuth .signInWithEmailAndPassword(mockFirebaseAuth, "email", "password") .subscribe(obs); callOnComplete(mockAuthResultTask); obs.dispose(); // Ensure no more values are emitted after unsubscribe callOnComplete(mockAuthResultTask); obs.assertError(IllegalStateException.class); obs.assertNoValues(); } @Test public void testSignOut() { TestObserver obs = TestObserver.create(); RxFirebaseAuth.signOut(mockFirebaseAuth) .subscribe(obs); verify(mockFirebaseAuth) .signOut(); obs.dispose(); obs.assertComplete(); } private void mockSuccessfulAuthResult() { when(mockAuthResult.getUser()) .thenReturn(mockFirebaseUser); when(mockAuthResultTask.isSuccessful()) .thenReturn(true); when(mockAuthResultTask.getResult()) .thenReturn(mockAuthResult); //noinspection unchecked when(mockAuthResultTask.addOnCompleteListener(onComplete.capture())) .thenReturn(mockAuthResultTask); } private void mockNotSuccessfulResult(Exception exception) { when(mockAuthResultTask.isSuccessful()) .thenReturn(false); when(mockAuthResultTask.getException()) .thenReturn(exception); //noinspection unchecked when(mockAuthResultTask.addOnCompleteListener(onComplete.capture())) .thenReturn(mockAuthResultTask); } private void mockSuccessfulSendPasswordResetEmailResult() { when(mockSendPasswordResetEmailTask.isSuccessful()) .thenReturn(true); //noinspection unchecked when(mockSendPasswordResetEmailTask.addOnCompleteListener(onComplete.capture())) .thenReturn(mockSendPasswordResetEmailTask); } private void mockNotSuccessfulSendPasswordResetEmailResult(Exception exception) { when(mockSendPasswordResetEmailTask.isSuccessful()) .thenReturn(false); when(mockSendPasswordResetEmailTask.getException()) .thenReturn(exception); //noinspection unchecked when(mockSendPasswordResetEmailTask.addOnCompleteListener(onComplete.capture())) .thenReturn(mockSendPasswordResetEmailTask); } private void mockSuccessfulFetchProvidersResult() { when(mockFetchProvidersTask.isSuccessful()) .thenReturn(true); ProviderQueryResult result = mock(ProviderQueryResult.class); when(result.getProviders()) .thenReturn(new ArrayList<String>()); when(mockFetchProvidersTask.getResult()) .thenReturn(result); //noinspection unchecked when(mockFetchProvidersTask.addOnCompleteListener(onComplete.capture())) .thenReturn(mockFetchProvidersTask); } private void mockNotSuccessfulFetchProvidersResult(Exception exception) { when(mockFetchProvidersTask.isSuccessful()) .thenReturn(false); when(mockFetchProvidersTask.getException()) .thenReturn(exception); //noinspection unchecked when(mockFetchProvidersTask.addOnCompleteListener(onComplete.capture())) .thenReturn(mockFetchProvidersTask); } @SuppressWarnings("unchecked") private void callOnComplete(Task<?> task) { verify(task) .addOnCompleteListener(onComplete.capture()); onComplete.getValue().onComplete(task); } private void callOnAuthStateChanged() { verify(mockFirebaseAuth) .addAuthStateListener(authStateChange.capture()); authStateChange.getValue().onAuthStateChanged(mockFirebaseAuth); } }