Repository: firebase/firebase-admin-java
Pull request #453 (2020-07-14 18:48:38)

Improve unit test coverage of tenant/provider-related code
I've improved the unit test coverage of tenant/provider-related code, and I've also removed a number of unused imports.

I used `mvn test -Djacoco` to generate the test coverage stats.


Patch:
diff --git a/src/main/java/com/google/firebase/auth/AbstractFirebaseAuth.java b/src/main/java/com/google/firebase/auth/AbstractFirebaseAuth.java
index 35f2227..ad30d2c 100644
--- a/src/main/java/com/google/firebase/auth/AbstractFirebaseAuth.java
+++ b/src/main/java/com/google/firebase/auth/AbstractFirebaseAuth.java
@@ -30,12 +30,9 @@ import com.google.common.base.Suppliers;
 import com.google.firebase.FirebaseApp;
 import com.google.firebase.auth.FirebaseUserManager.EmailLinkType;
 import com.google.firebase.auth.FirebaseUserManager.UserImportRequest;
-import com.google.firebase.auth.ListProviderConfigsPage;
 import com.google.firebase.auth.ListProviderConfigsPage.DefaultOidcProviderConfigSource;
 import com.google.firebase.auth.ListProviderConfigsPage.DefaultSamlProviderConfigSource;
-import com.google.firebase.auth.ListUsersPage;
 import com.google.firebase.auth.ListUsersPage.DefaultUserSource;
-import com.google.firebase.auth.UserRecord;
 import com.google.firebase.auth.internal.FirebaseTokenFactory;
 import com.google.firebase.internal.CallableOperation;
 import com.google.firebase.internal.NonNull;
diff --git a/src/main/java/com/google/firebase/auth/FirebaseUserManager.java b/src/main/java/com/google/firebase/auth/FirebaseUserManager.java
index a2c17aa..b738822 100644
--- a/src/main/java/com/google/firebase/auth/FirebaseUserManager.java
+++ b/src/main/java/com/google/firebase/auth/FirebaseUserManager.java
@@ -54,8 +54,6 @@ import java.util.Set;
  * FirebaseUserManager provides methods for interacting with the Google Identity Toolkit via its
  * REST API. This class does not hold any mutable state, and is thread safe.
  *
- * <p>TODO(micahstairs): Rename this class to IdentityToolkitClient.
- *
  * @see <a href="https://developers.google.com/identity/toolkit/web/reference/relyingparty">
  *   Google Identity Toolkit</a>
  */
diff --git a/src/main/java/com/google/firebase/auth/ListProviderConfigsPage.java b/src/main/java/com/google/firebase/auth/ListProviderConfigsPage.java
index 4530c0f..361f932 100644
--- a/src/main/java/com/google/firebase/auth/ListProviderConfigsPage.java
+++ b/src/main/java/com/google/firebase/auth/ListProviderConfigsPage.java
@@ -19,10 +19,8 @@ package com.google.firebase.auth;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 
-import com.google.api.client.json.JsonFactory;
 import com.google.api.gax.paging.Page;
 import com.google.common.collect.ImmutableList;
-import com.google.firebase.auth.internal.DownloadAccountResponse;
 import com.google.firebase.auth.internal.ListOidcProviderConfigsResponse;
 import com.google.firebase.auth.internal.ListProviderConfigsResponse;
 import com.google.firebase.auth.internal.ListSamlProviderConfigsResponse;
@@ -113,7 +111,7 @@ public class ListProviderConfigsPage<T extends ProviderConfig> implements Page<T
   @NonNull
   @Override
   public Iterable<T> iterateAll() {
-    return new ProviderConfigIterable(this);
+    return new ProviderConfigIterable<T>(this);
   }
 
   /**
@@ -248,7 +246,7 @@ public class ListProviderConfigsPage<T extends ProviderConfig> implements Page<T
     }
 
     Factory(
-        @NonNull ProviderConfigSource source,
+        @NonNull ProviderConfigSource<T> source,
         int maxResults,
         @Nullable String pageToken) {
       checkArgument(
diff --git a/src/main/java/com/google/firebase/auth/OidcProviderConfig.java b/src/main/java/com/google/firebase/auth/OidcProviderConfig.java
index 90a49e6..879b7e7 100644
--- a/src/main/java/com/google/firebase/auth/OidcProviderConfig.java
+++ b/src/main/java/com/google/firebase/auth/OidcProviderConfig.java
@@ -20,8 +20,6 @@ import static com.google.common.base.Preconditions.checkArgument;
 
 import com.google.api.client.util.Key;
 import com.google.common.base.Strings;
-import com.google.firebase.auth.ProviderConfig.AbstractCreateRequest;
-import com.google.firebase.auth.ProviderConfig.AbstractUpdateRequest;
 
 /**
  * Contains metadata associated with an OIDC Auth provider.
diff --git a/src/main/java/com/google/firebase/auth/SamlProviderConfig.java b/src/main/java/com/google/firebase/auth/SamlProviderConfig.java
index e74478b..76f8594 100644
--- a/src/main/java/com/google/firebase/auth/SamlProviderConfig.java
+++ b/src/main/java/com/google/firebase/auth/SamlProviderConfig.java
@@ -24,8 +24,6 @@ import com.google.api.client.util.Key;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import com.google.firebase.auth.ProviderConfig.AbstractCreateRequest;
-import com.google.firebase.auth.ProviderConfig.AbstractUpdateRequest;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
diff --git a/src/main/java/com/google/firebase/auth/internal/ListOidcProviderConfigsResponse.java b/src/main/java/com/google/firebase/auth/internal/ListOidcProviderConfigsResponse.java
index e8b5e20..187f98c 100644
--- a/src/main/java/com/google/firebase/auth/internal/ListOidcProviderConfigsResponse.java
+++ b/src/main/java/com/google/firebase/auth/internal/ListOidcProviderConfigsResponse.java
@@ -17,6 +17,7 @@
 package com.google.firebase.auth.internal;
 
 import com.google.api.client.util.Key;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.firebase.auth.OidcProviderConfig;
@@ -35,6 +36,15 @@ public final class ListOidcProviderConfigsResponse
   @Key("nextPageToken")
   private String pageToken;
 
+  @VisibleForTesting
+  public ListOidcProviderConfigsResponse(
+      List<OidcProviderConfig> providerConfigs, String pageToken) {
+    this.providerConfigs = providerConfigs;
+    this.pageToken = pageToken;
+  }
+
+  public ListOidcProviderConfigsResponse() { }
+
   @Override
   public List<OidcProviderConfig> getProviderConfigs() {
     return providerConfigs == null ? ImmutableList.<OidcProviderConfig>of() : providerConfigs;
diff --git a/src/main/java/com/google/firebase/auth/internal/ListSamlProviderConfigsResponse.java b/src/main/java/com/google/firebase/auth/internal/ListSamlProviderConfigsResponse.java
index 4386e21..55b944d 100644
--- a/src/main/java/com/google/firebase/auth/internal/ListSamlProviderConfigsResponse.java
+++ b/src/main/java/com/google/firebase/auth/internal/ListSamlProviderConfigsResponse.java
@@ -17,6 +17,7 @@
 package com.google.firebase.auth.internal;
 
 import com.google.api.client.util.Key;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.firebase.auth.SamlProviderConfig;
@@ -35,6 +36,15 @@ public final class ListSamlProviderConfigsResponse
   @Key("nextPageToken")
   private String pageToken;
 
+  @VisibleForTesting
+  public ListSamlProviderConfigsResponse(
+      List<SamlProviderConfig> providerConfigs, String pageToken) {
+    this.providerConfigs = providerConfigs;
+    this.pageToken = pageToken;
+  }
+
+  public ListSamlProviderConfigsResponse() { }
+
   @Override
   public List<SamlProviderConfig> getProviderConfigs() {
     return providerConfigs == null ? ImmutableList.<SamlProviderConfig>of() : providerConfigs;


Test patch:
diff --git a/src/test/java/com/google/firebase/auth/FirebaseAuthTest.java b/src/test/java/com/google/firebase/auth/FirebaseAuthTest.java
index b791105..635e1bf 100644
--- a/src/test/java/com/google/firebase/auth/FirebaseAuthTest.java
+++ b/src/test/java/com/google/firebase/auth/FirebaseAuthTest.java
@@ -32,7 +32,6 @@ import com.google.common.collect.ImmutableMap;
 import com.google.firebase.FirebaseApp;
 import com.google.firebase.FirebaseOptions;
 import com.google.firebase.TestOnlyImplFirebaseTrampolines;
-import com.google.firebase.auth.internal.FirebaseTokenFactory;
 import com.google.firebase.testing.ServiceAccount;
 import com.google.firebase.testing.TestUtils;
 import java.lang.reflect.InvocationTargetException;
diff --git a/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java b/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java
index 2702a1c..d407fd8 100644
--- a/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java
+++ b/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java
@@ -1422,6 +1422,33 @@ public class FirebaseUserManagerTest {
     assertEquals("oidc.provider-id", url.getFirst("oauthIdpConfigId"));
   }
 
+  @Test
+  public void testCreateOidcProviderAsync() throws Exception {
+    TestResponseInterceptor interceptor = initializeAppForUserManagement(
+        TestUtils.loadResource("oidc.json"));
+    OidcProviderConfig.CreateRequest createRequest =
+        new OidcProviderConfig.CreateRequest()
+            .setProviderId("oidc.provider-id")
+            .setDisplayName("DISPLAY_NAME")
+            .setEnabled(true)
+            .setClientId("CLIENT_ID")
+            .setIssuer("https://oidc.com/issuer");
+
+    OidcProviderConfig config = 
+        FirebaseAuth.getInstance().createOidcProviderConfigAsync(createRequest).get();
+
+    checkOidcProviderConfig(config, "oidc.provider-id");
+    checkRequestHeaders(interceptor);
+    checkUrl(interceptor, "POST", PROJECT_BASE_URL + "/oauthIdpConfigs");
+    GenericJson parsed = parseRequestContent(interceptor);
+    assertEquals("DISPLAY_NAME", parsed.get("displayName"));
+    assertTrue((boolean) parsed.get("enabled"));
+    assertEquals("CLIENT_ID", parsed.get("clientId"));
+    assertEquals("https://oidc.com/issuer", parsed.get("issuer"));
+    GenericUrl url = interceptor.getResponse().getRequest().getUrl();
+    assertEquals("oidc.provider-id", url.getFirst("oauthIdpConfigId"));
+  }
+
   @Test
   public void testCreateOidcProviderMinimal() throws Exception {
     TestResponseInterceptor interceptor = initializeAppForUserManagement(
@@ -1494,7 +1521,7 @@ public class FirebaseUserManagerTest {
     TenantAwareFirebaseAuth tenantAwareAuth =
         FirebaseAuth.getInstance().getTenantManager().getAuthForTenant("TENANT_ID");
 
-    OidcProviderConfig config = tenantAwareAuth.createOidcProviderConfig(createRequest);
+    tenantAwareAuth.createOidcProviderConfig(createRequest);
 
     checkRequestHeaders(interceptor);
     checkUrl(interceptor, "POST", TENANTS_BASE_URL + "/TENANT_ID/oauthIdpConfigs");
@@ -1525,6 +1552,32 @@ public class FirebaseUserManagerTest {
     assertEquals("https://oidc.com/issuer", parsed.get("issuer"));
   }
 
+  @Test
+  public void testUpdateOidcProviderAsync() throws Exception {
+    TestResponseInterceptor interceptor = initializeAppForUserManagement(
+        TestUtils.loadResource("oidc.json"));
+    OidcProviderConfig.UpdateRequest request =
+        new OidcProviderConfig.UpdateRequest("oidc.provider-id")
+            .setDisplayName("DISPLAY_NAME")
+            .setEnabled(true)
+            .setClientId("CLIENT_ID")
+            .setIssuer("https://oidc.com/issuer");
+
+    OidcProviderConfig config =
+        FirebaseAuth.getInstance().updateOidcProviderConfigAsync(request).get();
+
+    checkOidcProviderConfig(config, "oidc.provider-id");
+    checkRequestHeaders(interceptor);
+    checkUrl(interceptor, "PATCH", PROJECT_BASE_URL + "/oauthIdpConfigs/oidc.provider-id");
+    GenericUrl url = interceptor.getResponse().getRequest().getUrl();
+    assertEquals("clientId,displayName,enabled,issuer", url.getFirst("updateMask"));
+    GenericJson parsed = parseRequestContent(interceptor);
+    assertEquals("DISPLAY_NAME", parsed.get("displayName"));
+    assertTrue((boolean) parsed.get("enabled"));
+    assertEquals("CLIENT_ID", parsed.get("clientId"));
+    assertEquals("https://oidc.com/issuer", parsed.get("issuer"));
+  }
+
   @Test
   public void testUpdateOidcProviderMinimal() throws Exception {
     TestResponseInterceptor interceptor = initializeAppForUserManagement(
@@ -1614,6 +1667,19 @@ public class FirebaseUserManagerTest {
     checkUrl(interceptor, "GET", PROJECT_BASE_URL + "/oauthIdpConfigs/oidc.provider-id");
   }
 
+  @Test
+  public void testGetOidcProviderConfigAsync() throws Exception {
+    TestResponseInterceptor interceptor = initializeAppForUserManagement(
+        TestUtils.loadResource("oidc.json"));
+
+    OidcProviderConfig config =
+        FirebaseAuth.getInstance().getOidcProviderConfigAsync("oidc.provider-id").get();
+
+    checkOidcProviderConfig(config, "oidc.provider-id");
+    checkRequestHeaders(interceptor);
+    checkUrl(interceptor, "GET", PROJECT_BASE_URL + "/oauthIdpConfigs/oidc.provider-id");
+  }
+
   @Test
   public void testGetOidcProviderConfigMissingId() throws Exception {
     initializeAppForUserManagement(TestUtils.loadResource("oidc.json"));
@@ -1669,6 +1735,25 @@ public class FirebaseUserManagerTest {
 
   @Test
   public void testListOidcProviderConfigs() throws Exception {
+    final TestResponseInterceptor interceptor = initializeAppForUserManagement(
+        TestUtils.loadResource("listOidc.json"));
+    ListProviderConfigsPage<OidcProviderConfig> page =
+        FirebaseAuth.getInstance().listOidcProviderConfigs(null, 99);
+
+    ImmutableList<OidcProviderConfig> providerConfigs = ImmutableList.copyOf(page.getValues());
+    assertEquals(2, providerConfigs.size());
+    checkOidcProviderConfig(providerConfigs.get(0), "oidc.provider-id1");
+    checkOidcProviderConfig(providerConfigs.get(1), "oidc.provider-id2");
+    assertEquals("", page.getNextPageToken());
+    checkRequestHeaders(interceptor);
+    checkUrl(interceptor, "GET", PROJECT_BASE_URL + "/oauthIdpConfigs");
+    GenericUrl url = interceptor.getResponse().getRequest().getUrl();
+    assertEquals(99, url.getFirst("pageSize"));
+    assertNull(url.getFirst("nextPageToken"));
+  }
+
+  @Test
+  public void testListOidcProviderConfigsAsync() throws Exception {
     final TestResponseInterceptor interceptor = initializeAppForUserManagement(
         TestUtils.loadResource("listOidc.json"));
     ListProviderConfigsPage<OidcProviderConfig> page =
@@ -1686,12 +1771,27 @@ public class FirebaseUserManagerTest {
     assertNull(url.getFirst("nextPageToken"));
   }
 
+  @Test
+  public void testListOidcProviderConfigsError() throws Exception {
+    TestResponseInterceptor interceptor =
+        initializeAppForUserManagementWithStatusCode(404,
+            "{\"error\": {\"message\": \"INTERNAL_ERROR\"}}");
+
+    try {
+      FirebaseAuth.getInstance().listOidcProviderConfigs(null, 99);
+      fail("No error thrown for invalid response");
+    } catch (FirebaseAuthException e) {
+      assertEquals(AuthHttpClient.INTERNAL_ERROR, e.getErrorCode());
+    }
+    checkUrl(interceptor, "GET", PROJECT_BASE_URL + "/oauthIdpConfigs");
+  }
+
   @Test
   public void testListOidcProviderConfigsWithPageToken() throws Exception {
     final TestResponseInterceptor interceptor = initializeAppForUserManagement(
         TestUtils.loadResource("listOidc.json"));
     ListProviderConfigsPage<OidcProviderConfig> page =
-        FirebaseAuth.getInstance().listOidcProviderConfigsAsync("token", 99).get();
+        FirebaseAuth.getInstance().listOidcProviderConfigs("token", 99);
 
     ImmutableList<OidcProviderConfig> providerConfigs = ImmutableList.copyOf(page.getValues());
     assertEquals(2, providerConfigs.size());
@@ -1709,7 +1809,7 @@ public class FirebaseUserManagerTest {
   public void testListZeroOidcProviderConfigs() throws Exception {
     TestResponseInterceptor interceptor = initializeAppForUserManagement("{}");
     ListProviderConfigsPage<OidcProviderConfig> page =
-        FirebaseAuth.getInstance().listOidcProviderConfigsAsync(null).get();
+        FirebaseAuth.getInstance().listOidcProviderConfigs(null);
     assertTrue(Iterables.isEmpty(page.getValues()));
     assertEquals("", page.getNextPageToken());
     checkRequestHeaders(interceptor);
@@ -1723,7 +1823,7 @@ public class FirebaseUserManagerTest {
     TenantAwareFirebaseAuth tenantAwareAuth =
         FirebaseAuth.getInstance().getTenantManager().getAuthForTenant("TENANT_ID");
     ListProviderConfigsPage<OidcProviderConfig> page =
-        tenantAwareAuth.listOidcProviderConfigsAsync(null, 99).get();
+        tenantAwareAuth.listOidcProviderConfigs(null, 99);
 
     ImmutableList<OidcProviderConfig> providerConfigs = ImmutableList.copyOf(page.getValues());
     assertEquals(2, providerConfigs.size());
@@ -1747,6 +1847,16 @@ public class FirebaseUserManagerTest {
     checkUrl(interceptor, "DELETE", PROJECT_BASE_URL + "/oauthIdpConfigs/oidc.provider-id");
   }
 
+  @Test
+  public void testDeleteOidcProviderConfigAsync() throws Exception {
+    TestResponseInterceptor interceptor = initializeAppForUserManagement("{}");
+
+    FirebaseAuth.getInstance().deleteOidcProviderConfigAsync("oidc.provider-id").get();
+
+    checkRequestHeaders(interceptor);
+    checkUrl(interceptor, "DELETE", PROJECT_BASE_URL + "/oauthIdpConfigs/oidc.provider-id");
+  }
+
   @Test
   public void testDeleteOidcProviderMissingId() throws Exception {
     initializeAppForUserManagement("{}");
@@ -1846,6 +1956,53 @@ public class FirebaseUserManagerTest {
     assertEquals("https://projectId.firebaseapp.com/__/auth/handler", spConfig.get("callbackUri"));
   }
 
+  @Test
+  public void testCreateSamlProviderAsync() throws Exception {
+    TestResponseInterceptor interceptor = initializeAppForUserManagement(
+        TestUtils.loadResource("saml.json"));
+    SamlProviderConfig.CreateRequest createRequest =
+        new SamlProviderConfig.CreateRequest()
+          .setProviderId("saml.provider-id")
+          .setDisplayName("DISPLAY_NAME")
+          .setEnabled(true)
+          .setIdpEntityId("IDP_ENTITY_ID")
+          .setSsoUrl("https://example.com/login")
+          .addX509Certificate("certificate1")
+          .addX509Certificate("certificate2")
+          .setRpEntityId("RP_ENTITY_ID")
+          .setCallbackUrl("https://projectId.firebaseapp.com/__/auth/handler");
+
+    SamlProviderConfig config =
+        FirebaseAuth.getInstance().createSamlProviderConfigAsync(createRequest).get();
+
+    checkSamlProviderConfig(config, "saml.provider-id");
+    checkRequestHeaders(interceptor);
+    checkUrl(interceptor, "POST", PROJECT_BASE_URL + "/inboundSamlConfigs");
+    GenericUrl url = interceptor.getResponse().getRequest().getUrl();
+    assertEquals("saml.provider-id", url.getFirst("inboundSamlConfigId"));
+
+    GenericJson parsed = parseRequestContent(interceptor);
+    assertEquals("DISPLAY_NAME", parsed.get("displayName"));
+    assertTrue((boolean) parsed.get("enabled"));
+
+    Map<String, Object> idpConfig = (Map<String, Object>) parsed.get("idpConfig");
+    assertNotNull(idpConfig);
+    assertEquals(3, idpConfig.size());
+    assertEquals("IDP_ENTITY_ID", idpConfig.get("idpEntityId"));
+    assertEquals("https://example.com/login", idpConfig.get("ssoUrl"));
+    List<Object> idpCertificates = (List<Object>) idpConfig.get("idpCertificates");
+    assertNotNull(idpCertificates);
+    assertEquals(2, idpCertificates.size());
+    assertEquals(ImmutableMap.of("x509Certificate", "certificate1"), idpCertificates.get(0));
+    assertEquals(ImmutableMap.of("x509Certificate", "certificate2"), idpCertificates.get(1));
+
+    Map<String, Object> spConfig = (Map<String, Object>) parsed.get("spConfig");
+    assertNotNull(spConfig);
+    assertEquals(2, spConfig.size());
+    assertEquals("RP_ENTITY_ID", spConfig.get("spEntityId"));
+    assertEquals("https://projectId.firebaseapp.com/__/auth/handler", spConfig.get("callbackUri"));
+  }
+
   @Test
   public void testCreateSamlProviderMinimal() throws Exception {
     TestResponseInterceptor interceptor = initializeAppForUserManagement(
@@ -1997,6 +2154,55 @@ public class FirebaseUserManagerTest {
     assertEquals("https://projectId.firebaseapp.com/__/auth/handler", spConfig.get("callbackUri"));
   }
 
+  @Test
+  public void testUpdateSamlProviderAsync() throws Exception {
+    TestResponseInterceptor interceptor = initializeAppForUserManagement(
+        TestUtils.loadResource("saml.json"));
+    SamlProviderConfig.UpdateRequest updateRequest =
+        new SamlProviderConfig.UpdateRequest("saml.provider-id")
+          .setDisplayName("DISPLAY_NAME")
+          .setEnabled(true)
+          .setIdpEntityId("IDP_ENTITY_ID")
+          .setSsoUrl("https://example.com/login")
+          .addX509Certificate("certificate1")
+          .addX509Certificate("certificate2")
+          .setRpEntityId("RP_ENTITY_ID")
+          .setCallbackUrl("https://projectId.firebaseapp.com/__/auth/handler");
+
+    SamlProviderConfig config =
+        FirebaseAuth.getInstance().updateSamlProviderConfigAsync(updateRequest).get();
+
+    checkSamlProviderConfig(config, "saml.provider-id");
+    checkRequestHeaders(interceptor);
+    checkUrl(interceptor, "PATCH", PROJECT_BASE_URL + "/inboundSamlConfigs/saml.provider-id");
+    GenericUrl url = interceptor.getResponse().getRequest().getUrl();
+    assertEquals(
+        "displayName,enabled,idpConfig.idpCertificates,idpConfig.idpEntityId,idpConfig.ssoUrl,"
+          + "spConfig.callbackUri,spConfig.spEntityId",
+        url.getFirst("updateMask"));
+
+    GenericJson parsed = parseRequestContent(interceptor);
+    assertEquals("DISPLAY_NAME", parsed.get("displayName"));
+    assertTrue((boolean) parsed.get("enabled"));
+
+    Map<String, Object> idpConfig = (Map<String, Object>) parsed.get("idpConfig");
+    assertNotNull(idpConfig);
+    assertEquals(3, idpConfig.size());
+    assertEquals("IDP_ENTITY_ID", idpConfig.get("idpEntityId"));
+    assertEquals("https://example.com/login", idpConfig.get("ssoUrl"));
+    List<Object> idpCertificates = (List<Object>) idpConfig.get("idpCertificates");
+    assertNotNull(idpCertificates);
+    assertEquals(2, idpCertificates.size());
+    assertEquals(ImmutableMap.of("x509Certificate", "certificate1"), idpCertificates.get(0));
+    assertEquals(ImmutableMap.of("x509Certificate", "certificate2"), idpCertificates.get(1));
+
+    Map<String, Object> spConfig = (Map<String, Object>) parsed.get("spConfig");
+    assertNotNull(spConfig);
+    assertEquals(2, spConfig.size());
+    assertEquals("RP_ENTITY_ID", spConfig.get("spEntityId"));
+    assertEquals("https://projectId.firebaseapp.com/__/auth/handler", spConfig.get("callbackUri"));
+  }
+
   @Test
   public void testUpdateSamlProviderMinimal() throws Exception {
     TestResponseInterceptor interceptor = initializeAppForUserManagement(
@@ -2018,8 +2224,7 @@ public class FirebaseUserManagerTest {
 
   @Test
   public void testUpdateSamlProviderConfigNoValues() throws Exception {
-    TestResponseInterceptor interceptor = initializeAppForUserManagement(
-        TestUtils.loadResource("saml.json"));
+    initializeAppForUserManagement(TestUtils.loadResource("saml.json"));
     try {
       FirebaseAuth.getInstance().updateSamlProviderConfig(
           new SamlProviderConfig.UpdateRequest("saml.provider-id"));
@@ -2092,6 +2297,19 @@ public class FirebaseUserManagerTest {
     checkUrl(interceptor, "GET", PROJECT_BASE_URL + "/inboundSamlConfigs/saml.provider-id");
   }
 
+  @Test
+  public void testGetSamlProviderConfigAsync() throws Exception {
+    TestResponseInterceptor interceptor = initializeAppForUserManagement(
+        TestUtils.loadResource("saml.json"));
+
+    SamlProviderConfig config =
+        FirebaseAuth.getInstance().getSamlProviderConfigAsync("saml.provider-id").get();
+
+    checkSamlProviderConfig(config, "saml.provider-id");
+    checkRequestHeaders(interceptor);
+    checkUrl(interceptor, "GET", PROJECT_BASE_URL + "/inboundSamlConfigs/saml.provider-id");
+  }
+
   @Test
   public void testGetSamlProviderConfigMissingId() throws Exception {
     initializeAppForUserManagement(TestUtils.loadResource("saml.json"));
@@ -2148,6 +2366,25 @@ public class FirebaseUserManagerTest {
 
   @Test
   public void testListSamlProviderConfigs() throws Exception {
+    final TestResponseInterceptor interceptor = initializeAppForUserManagement(
+        TestUtils.loadResource("listSaml.json"));
+    ListProviderConfigsPage<SamlProviderConfig> page =
+        FirebaseAuth.getInstance().listSamlProviderConfigs(null, 99);
+
+    ImmutableList<SamlProviderConfig> providerConfigs = ImmutableList.copyOf(page.getValues());
+    assertEquals(2, providerConfigs.size());
+    checkSamlProviderConfig(providerConfigs.get(0), "saml.provider-id1");
+    checkSamlProviderConfig(providerConfigs.get(1), "saml.provider-id2");
+    assertEquals("", page.getNextPageToken());
+    checkRequestHeaders(interceptor);
+    checkUrl(interceptor, "GET", PROJECT_BASE_URL + "/inboundSamlConfigs");
+    GenericUrl url = interceptor.getResponse().getRequest().getUrl();
+    assertEquals(99, url.getFirst("pageSize"));
+    assertNull(url.getFirst("nextPageToken"));
+  }
+
+  @Test
+  public void testListSamlProviderConfigsAsync() throws Exception {
     final TestResponseInterceptor interceptor = initializeAppForUserManagement(
         TestUtils.loadResource("listSaml.json"));
     ListProviderConfigsPage<SamlProviderConfig> page =
@@ -2165,12 +2402,27 @@ public class FirebaseUserManagerTest {
     assertNull(url.getFirst("nextPageToken"));
   }
 
+  @Test
+  public void testListSamlProviderConfigsError() throws Exception {
+    TestResponseInterceptor interceptor =
+        initializeAppForUserManagementWithStatusCode(404,
+            "{\"error\": {\"message\": \"INTERNAL_ERROR\"}}");
+
+    try {
+      FirebaseAuth.getInstance().listSamlProviderConfigs(null, 99);
+      fail("No error thrown for invalid response");
+    } catch (FirebaseAuthException e) {
+      assertEquals(AuthHttpClient.INTERNAL_ERROR, e.getErrorCode());
+    }
+    checkUrl(interceptor, "GET", PROJECT_BASE_URL + "/inboundSamlConfigs");
+  }
+
   @Test
   public void testListSamlProviderConfigsWithPageToken() throws Exception {
     final TestResponseInterceptor interceptor = initializeAppForUserManagement(
         TestUtils.loadResource("listSaml.json"));
     ListProviderConfigsPage<SamlProviderConfig> page =
-        FirebaseAuth.getInstance().listSamlProviderConfigsAsync("token", 99).get();
+        FirebaseAuth.getInstance().listSamlProviderConfigs("token", 99);
 
     ImmutableList<SamlProviderConfig> providerConfigs = ImmutableList.copyOf(page.getValues());
     assertEquals(2, providerConfigs.size());
@@ -2188,7 +2440,7 @@ public class FirebaseUserManagerTest {
   public void testListZeroSamlProviderConfigs() throws Exception {
     TestResponseInterceptor interceptor = initializeAppForUserManagement("{}");
     ListProviderConfigsPage<SamlProviderConfig> page =
-        FirebaseAuth.getInstance().listSamlProviderConfigsAsync(null).get();
+        FirebaseAuth.getInstance().listSamlProviderConfigs(null);
     assertTrue(Iterables.isEmpty(page.getValues()));
     assertEquals("", page.getNextPageToken());
     checkRequestHeaders(interceptor);
@@ -2202,7 +2454,7 @@ public class FirebaseUserManagerTest {
     TenantAwareFirebaseAuth tenantAwareAuth =
         FirebaseAuth.getInstance().getTenantManager().getAuthForTenant("TENANT_ID");
     ListProviderConfigsPage<SamlProviderConfig> page =
-        tenantAwareAuth.listSamlProviderConfigsAsync(null, 99).get();
+        tenantAwareAuth.listSamlProviderConfigs(null, 99);
 
     ImmutableList<SamlProviderConfig> providerConfigs = ImmutableList.copyOf(page.getValues());
     assertEquals(2, providerConfigs.size());
@@ -2226,6 +2478,16 @@ public class FirebaseUserManagerTest {
     checkUrl(interceptor, "DELETE", PROJECT_BASE_URL + "/inboundSamlConfigs/saml.provider-id");
   }
 
+  @Test
+  public void testDeleteSamlProviderConfigAsync() throws Exception {
+    TestResponseInterceptor interceptor = initializeAppForUserManagement("{}");
+
+    FirebaseAuth.getInstance().deleteSamlProviderConfigAsync("saml.provider-id").get();
+
+    checkRequestHeaders(interceptor);
+    checkUrl(interceptor, "DELETE", PROJECT_BASE_URL + "/inboundSamlConfigs/saml.provider-id");
+  }
+
   @Test
   public void testDeleteSamlProviderMissingId() throws Exception {
     initializeAppForUserManagement("{}");
diff --git a/src/test/java/com/google/firebase/auth/ListProviderConfigsPageTest.java b/src/test/java/com/google/firebase/auth/ListProviderConfigsPageTest.java
new file mode 100644
index 0000000..ba08f9c
--- /dev/null
+++ b/src/test/java/com/google/firebase/auth/ListProviderConfigsPageTest.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.firebase.auth;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import com.google.api.client.googleapis.util.Utils;
+import com.google.common.collect.ImmutableList;
+import com.google.firebase.auth.internal.ListOidcProviderConfigsResponse;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.junit.Test;
+
+public class ListProviderConfigsPageTest {
+
+  @Test
+  public void testSinglePage() throws FirebaseAuthException, IOException {
+    TestProviderConfigSource source = new TestProviderConfigSource(3);
+    ListProviderConfigsPage<OidcProviderConfig> page =
+        new ListProviderConfigsPage.Factory<OidcProviderConfig>(source).create();
+    assertFalse(page.hasNextPage());
+    assertEquals(ListProviderConfigsPage.END_OF_LIST, page.getNextPageToken());
+    assertNull(page.getNextPage());
+
+    ImmutableList<OidcProviderConfig> providerConfigs = ImmutableList.copyOf(page.getValues());
+    assertEquals(3, providerConfigs.size());
+    for (int i = 0; i < 3; i++) {
+      assertEquals("oidc.provider-id-" + i, providerConfigs.get(i).getProviderId());
+    }
+    assertEquals(1, source.calls.size());
+    assertNull(source.calls.get(0));
+  }
+
+  @Test
+  public void testMultiplePages() throws FirebaseAuthException, IOException {
+    ListOidcProviderConfigsResponse response = new ListOidcProviderConfigsResponse(
+        ImmutableList.of(
+          newOidcProviderConfig("oidc.provider-id-0"),
+          newOidcProviderConfig("oidc.provider-id-1"),
+          newOidcProviderConfig("oidc.provider-id-2")),
+        "token");
+    TestProviderConfigSource source = new TestProviderConfigSource(response);
+    ListProviderConfigsPage<OidcProviderConfig> page1 =
+        new ListProviderConfigsPage.Factory<OidcProviderConfig>(source).create();
+    assertTrue(page1.hasNextPage());
+    assertEquals("token", page1.getNextPageToken());
+    ImmutableList<OidcProviderConfig> providerConfigs = ImmutableList.copyOf(page1.getValues());
+    assertEquals(3, providerConfigs.size());
+    for (int i = 0; i < 3; i++) {
+      assertEquals("oidc.provider-id-" + i, providerConfigs.get(i).getProviderId());
+    }
+
+    response = new ListOidcProviderConfigsResponse(
+        ImmutableList.of(
+          newOidcProviderConfig("oidc.provider-id-3"),
+          newOidcProviderConfig("oidc.provider-id-4"),
+          newOidcProviderConfig("oidc.provider-id-5")),
+        ListProviderConfigsPage.END_OF_LIST);
+    source.response = response;
+    ListProviderConfigsPage<OidcProviderConfig> page2 = page1.getNextPage();
+    assertFalse(page2.hasNextPage());
+    assertEquals(ListProviderConfigsPage.END_OF_LIST, page2.getNextPageToken());
+    providerConfigs = ImmutableList.copyOf(page2.getValues());
+    assertEquals(3, providerConfigs.size());
+    for (int i = 3; i < 6; i++) {
+      assertEquals("oidc.provider-id-" + i, providerConfigs.get(i - 3).getProviderId());
+    }
+
+    assertEquals(2, source.calls.size());
+    assertNull(source.calls.get(0));
+    assertEquals("token", source.calls.get(1));
+
+    // Should iterate all provider configs from both pages
+    int iterations = 0;
+    for (OidcProviderConfig providerConfig : page1.iterateAll()) {
+      iterations++;
+    }
+    assertEquals(6, iterations);
+    assertEquals(3, source.calls.size());
+    assertEquals("token", source.calls.get(2));
+
+    // Should only iterate provider configs in the last page
+    iterations = 0;
+    for (OidcProviderConfig providerConfig : page2.iterateAll()) {
+      iterations++;
+    }
+    assertEquals(3, iterations);
+    assertEquals(3, source.calls.size());
+  }
+
+  @Test
+  public void testListProviderConfigsIterable() throws FirebaseAuthException, IOException {
+    TestProviderConfigSource source = new TestProviderConfigSource(3);
+    ListProviderConfigsPage<OidcProviderConfig> page =
+        new ListProviderConfigsPage.Factory<OidcProviderConfig>(source).create();
+    Iterable<OidcProviderConfig> providerConfigs = page.iterateAll();
+
+    int iterations = 0;
+    for (OidcProviderConfig providerConfig : providerConfigs) {
+      assertEquals("oidc.provider-id-" + iterations, providerConfig.getProviderId());
+      iterations++;
+    }
+    assertEquals(3, iterations);
+    assertEquals(1, source.calls.size());
+    assertNull(source.calls.get(0));
+
+    // Should result in a new iterator
+    iterations = 0;
+    for (OidcProviderConfig providerConfig : providerConfigs) {
+      assertEquals("oidc.provider-id-" + iterations, providerConfig.getProviderId());
+      iterations++;
+    }
+    assertEquals(3, iterations);
+    assertEquals(1, source.calls.size());
+    assertNull(source.calls.get(0));
+  }
+
+  @Test
+  public void testListProviderConfigsIterator() throws FirebaseAuthException, IOException {
+    TestProviderConfigSource source = new TestProviderConfigSource(3);
+    ListProviderConfigsPage<OidcProviderConfig> page =
+        new ListProviderConfigsPage.Factory<OidcProviderConfig>(source).create();
+    Iterable<OidcProviderConfig> providerConfigs = page.iterateAll();
+    Iterator<OidcProviderConfig> iterator = providerConfigs.iterator();
+    int iterations = 0;
+    while (iterator.hasNext()) {
+      assertEquals("oidc.provider-id-" + iterations, iterator.next().getProviderId());
+      iterations++;
+    }
+    assertEquals(3, iterations);
+    assertEquals(1, source.calls.size());
+    assertNull(source.calls.get(0));
+
+    while (iterator.hasNext()) {
+      fail("Should not be able to to iterate any more");
+    }
+    try {
+      iterator.next();
+      fail("Should not be able to iterate any more");
+    } catch (NoSuchElementException expected) {
+      // expected
+    }
+    assertEquals(1, source.calls.size());
+  }
+
+  @Test
+  public void testListProviderConfigsPagedIterable() throws FirebaseAuthException, IOException {
+    ListOidcProviderConfigsResponse response = new ListOidcProviderConfigsResponse(
+        ImmutableList.of(
+          newOidcProviderConfig("oidc.provider-id-0"),
+          newOidcProviderConfig("oidc.provider-id-1"),
+          newOidcProviderConfig("oidc.provider-id-2")),
+        "token");
+    TestProviderConfigSource source = new TestProviderConfigSource(response);
+    ListProviderConfigsPage<OidcProviderConfig> page =
+        new ListProviderConfigsPage.Factory<OidcProviderConfig>(source).create();
+    int iterations = 0;
+    for (OidcProviderConfig providerConfig : page.iterateAll()) {
+      assertEquals("oidc.provider-id-" + iterations, providerConfig.getProviderId());
+      iterations++;
+      if (iterations == 3) {
+        assertEquals(1, source.calls.size());
+        assertNull(source.calls.get(0));
+        response = new ListOidcProviderConfigsResponse(
+            ImmutableList.of(
+              newOidcProviderConfig("oidc.provider-id-3"),
+              newOidcProviderConfig("oidc.provider-id-4"),
+              newOidcProviderConfig("oidc.provider-id-5")),
+            ListProviderConfigsPage.END_OF_LIST);
+        source.response = response;
+      }
+    }
+
+    assertEquals(6, iterations);
+    assertEquals(2, source.calls.size());
+    assertEquals("token", source.calls.get(1));
+  }
+
+  @Test
+  public void testListProviderConfigsPagedIterator() throws FirebaseAuthException, IOException {
+    ListOidcProviderConfigsResponse response = new ListOidcProviderConfigsResponse(
+        ImmutableList.of(
+          newOidcProviderConfig("oidc.provider-id-0"),
+          newOidcProviderConfig("oidc.provider-id-1"),
+          newOidcProviderConfig("oidc.provider-id-2")),
+        "token");
+    TestProviderConfigSource source = new TestProviderConfigSource(response);
+    ListProviderConfigsPage<OidcProviderConfig> page =
+        new ListProviderConfigsPage.Factory<OidcProviderConfig>(source).create();
+    Iterator<OidcProviderConfig> providerConfigs = page.iterateAll().iterator();
+    int iterations = 0;
+    while (providerConfigs.hasNext()) {
+      assertEquals("oidc.provider-id-" + iterations, providerConfigs.next().getProviderId());
+      iterations++;
+      if (iterations == 3) {
+        assertEquals(1, source.calls.size());
+        assertNull(source.calls.get(0));
+        response = new ListOidcProviderConfigsResponse(
+            ImmutableList.of(
+              newOidcProviderConfig("oidc.provider-id-3"),
+              newOidcProviderConfig("oidc.provider-id-4"),
+              newOidcProviderConfig("oidc.provider-id-5")),
+            ListProviderConfigsPage.END_OF_LIST);
+        source.response = response;
+      }
+    }
+
+    assertEquals(6, iterations);
+    assertEquals(2, source.calls.size());
+    assertEquals("token", source.calls.get(1));
+    assertFalse(providerConfigs.hasNext());
+    try {
+      providerConfigs.next();
+    } catch (NoSuchElementException e) {
+      // expected
+    }
+  }
+
+  @Test
+  public void testPageWithNoproviderConfigs() throws FirebaseAuthException {
+    ListOidcProviderConfigsResponse response = new ListOidcProviderConfigsResponse(
+        ImmutableList.<OidcProviderConfig>of(), ListProviderConfigsPage.END_OF_LIST);
+    TestProviderConfigSource source = new TestProviderConfigSource(response);
+    ListProviderConfigsPage<OidcProviderConfig> page =
+        new ListProviderConfigsPage.Factory<OidcProviderConfig>(source).create();
+    assertFalse(page.hasNextPage());
+    assertEquals(ListProviderConfigsPage.END_OF_LIST, page.getNextPageToken());
+    assertNull(page.getNextPage());
+    assertEquals(0, ImmutableList.copyOf(page.getValues()).size());
+    assertEquals(1, source.calls.size());
+  }
+
+  @Test
+  public void testIterableWithNoproviderConfigs() throws FirebaseAuthException {
+    ListOidcProviderConfigsResponse response = new ListOidcProviderConfigsResponse(
+        ImmutableList.<OidcProviderConfig>of(), ListProviderConfigsPage.END_OF_LIST);
+    TestProviderConfigSource source = new TestProviderConfigSource(response);
+    ListProviderConfigsPage<OidcProviderConfig> page =
+        new ListProviderConfigsPage.Factory<OidcProviderConfig>(source).create();
+    for (OidcProviderConfig providerConfig : page.iterateAll()) {
+      fail("Should not be able to iterate, but got: " + providerConfig);
+    }
+    assertEquals(1, source.calls.size());
+  }
+
+  @Test
+  public void testIteratorWithNoproviderConfigs() throws FirebaseAuthException {
+    ListOidcProviderConfigsResponse response = new ListOidcProviderConfigsResponse(
+        ImmutableList.<OidcProviderConfig>of(), ListProviderConfigsPage.END_OF_LIST);
+    TestProviderConfigSource source = new TestProviderConfigSource(response);
+
+    ListProviderConfigsPage<OidcProviderConfig> page =
+        new ListProviderConfigsPage.Factory<OidcProviderConfig>(source).create();
+    Iterator<OidcProviderConfig> iterator = page.iterateAll().iterator();
+    while (iterator.hasNext()) {
+      fail("Should not be able to iterate");
+    }
+    assertEquals(1, source.calls.size());
+  }
+
+  @Test
+  public void testRemove() throws FirebaseAuthException, IOException {
+    ListOidcProviderConfigsResponse response = new ListOidcProviderConfigsResponse(
+        ImmutableList.of(newOidcProviderConfig("oidc.provider-id-1")),
+        ListProviderConfigsPage.END_OF_LIST);
+    TestProviderConfigSource source = new TestProviderConfigSource(response);
+
+    ListProviderConfigsPage<OidcProviderConfig> page =
+        new ListProviderConfigsPage.Factory<OidcProviderConfig>(source).create();
+    Iterator<OidcProviderConfig> iterator = page.iterateAll().iterator();
+    while (iterator.hasNext()) {
+      assertNotNull(iterator.next());
+      try {
+        iterator.remove();
+      } catch (UnsupportedOperationException expected) {
+        // expected
+      }
+    }
+  }
+
+  @Test(expected = NullPointerException.class)
+  public void testNullSource() {
+    new ListProviderConfigsPage.Factory<OidcProviderConfig>(null);
+  }
+
+  @Test
+  public void testInvalidPageToken() throws IOException {
+    TestProviderConfigSource source = new TestProviderConfigSource(1);
+    try {
+      new ListProviderConfigsPage.Factory<OidcProviderConfig>(source, 1000, "");
+      fail("No error thrown for empty page token");
+    } catch (IllegalArgumentException expected) {
+      // expected
+    }
+  }
+
+  @Test
+  public void testInvalidMaxResults() throws IOException {
+    TestProviderConfigSource source = new TestProviderConfigSource(1);
+    try {
+      new ListProviderConfigsPage.Factory<OidcProviderConfig>(source, 1001, "");
+      fail("No error thrown for maxResult > 1000");
+    } catch (IllegalArgumentException expected) {
+      // expected
+    }
+
+    try {
+      new ListProviderConfigsPage.Factory<OidcProviderConfig>(source, 0, "next");
+      fail("No error thrown for maxResult = 0");
+    } catch (IllegalArgumentException expected) {
+      // expected
+    }
+
+    try {
+      new ListProviderConfigsPage.Factory<OidcProviderConfig>(source, -1, "next");
+      fail("No error thrown for maxResult < 0");
+    } catch (IllegalArgumentException expected) {
+      // expected
+    }
+  }
+
+  private static OidcProviderConfig newOidcProviderConfig(String providerConfigId)
+      throws IOException {
+    return Utils.getDefaultJsonFactory().fromString(
+        String.format("{\"name\":\"%s\"}", providerConfigId), OidcProviderConfig.class);
+  }
+
+  private static class TestProviderConfigSource
+      implements ListProviderConfigsPage.ProviderConfigSource<OidcProviderConfig> {
+
+    private ListOidcProviderConfigsResponse response;
+    private final List<String> calls = new ArrayList<>();
+
+    TestProviderConfigSource(int providerConfigCount) throws IOException {
+      ImmutableList.Builder<OidcProviderConfig> providerConfigs = ImmutableList.builder();
+      for (int i = 0; i < providerConfigCount; i++) {
+        providerConfigs.add(newOidcProviderConfig("oidc.provider-id-" + i));
+      }
+      this.response = new ListOidcProviderConfigsResponse(
+        providerConfigs.build(), ListProviderConfigsPage.END_OF_LIST);
+    }
+
+    TestProviderConfigSource(ListOidcProviderConfigsResponse response) {
+      this.response = response;
+    }
+
+    @Override
+    public ListOidcProviderConfigsResponse fetch(int maxResults, String pageToken) {
+      calls.add(pageToken);
+      return response;
+    }
+  }
+}
diff --git a/src/test/java/com/google/firebase/auth/OidcProviderConfigTest.java b/src/test/java/com/google/firebase/auth/OidcProviderConfigTest.java
index fa5c6d4..1fb4ca3 100644
--- a/src/test/java/com/google/firebase/auth/OidcProviderConfigTest.java
+++ b/src/test/java/com/google/firebase/auth/OidcProviderConfigTest.java
@@ -18,7 +18,6 @@ package com.google.firebase.auth;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import com.google.api.client.googleapis.util.Utils;
diff --git a/src/test/java/com/google/firebase/auth/ProviderConfigTestUtils.java b/src/test/java/com/google/firebase/auth/ProviderConfigTestUtils.java
index c01ac65..712a8ce 100644
--- a/src/test/java/com/google/firebase/auth/ProviderConfigTestUtils.java
+++ b/src/test/java/com/google/firebase/auth/ProviderConfigTestUtils.java
@@ -18,13 +18,11 @@ package com.google.firebase.auth;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import com.google.firebase.auth.internal.AuthHttpClient;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
 import org.junit.rules.ExternalResource;
 
 public class ProviderConfigTestUtils {
@@ -32,10 +30,9 @@ public class ProviderConfigTestUtils {
   public static void assertOidcProviderConfigDoesNotExist(
       AbstractFirebaseAuth firebaseAuth, String providerId) throws Exception {
     try {
-      firebaseAuth.getOidcProviderConfigAsync(providerId).get();
+      firebaseAuth.getOidcProviderConfig(providerId);
       fail("No error thrown for getting a deleted OIDC provider config.");
-    } catch (ExecutionException e) {
-      assertTrue(e.getCause() instanceof FirebaseAuthException);
+    } catch (FirebaseAuthException e) {
       assertEquals(AuthHttpClient.CONFIGURATION_NOT_FOUND_ERROR,
           ((FirebaseAuthException) e.getCause()).getErrorCode());
     }
@@ -44,10 +41,9 @@ public class ProviderConfigTestUtils {
   public static void assertSamlProviderConfigDoesNotExist(
       AbstractFirebaseAuth firebaseAuth, String providerId) throws Exception {
     try {
-      firebaseAuth.getSamlProviderConfigAsync(providerId).get();
+      firebaseAuth.getSamlProviderConfig(providerId);
       fail("No error thrown for getting a deleted SAML provider config.");
-    } catch (ExecutionException e) {
-      assertTrue(e.getCause() instanceof FirebaseAuthException);
+    } catch (FirebaseAuthException e) {
       assertEquals(AuthHttpClient.CONFIGURATION_NOT_FOUND_ERROR,
           ((FirebaseAuthException) e.getCause()).getErrorCode());
     }
diff --git a/src/test/java/com/google/firebase/auth/SamlProviderConfigTest.java b/src/test/java/com/google/firebase/auth/SamlProviderConfigTest.java
index 1351752..e957c1d 100644
--- a/src/test/java/com/google/firebase/auth/SamlProviderConfigTest.java
+++ b/src/test/java/com/google/firebase/auth/SamlProviderConfigTest.java
@@ -19,7 +19,6 @@ package com.google.firebase.auth;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import com.google.api.client.googleapis.util.Utils;
diff --git a/src/test/java/com/google/firebase/auth/internal/ListOidcProviderConfigsResponseTest.java b/src/test/java/com/google/firebase/auth/internal/ListOidcProviderConfigsResponseTest.java
new file mode 100644
index 0000000..fbe587e
--- /dev/null
+++ b/src/test/java/com/google/firebase/auth/internal/ListOidcProviderConfigsResponseTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.firebase.auth.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.api.client.googleapis.util.Utils;
+import com.google.api.client.json.JsonFactory;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.firebase.auth.OidcProviderConfig;
+
+import org.junit.Test;
+
+public class ListOidcProviderConfigsResponseTest {
+
+  private static final JsonFactory JSON_FACTORY = Utils.getDefaultJsonFactory();
+
+  @Test
+  public void testDefaultValues() throws Exception {
+    ListOidcProviderConfigsResponse response = new ListOidcProviderConfigsResponse();
+
+    assertEquals(0, response.getProviderConfigs().size());
+    assertFalse(response.hasProviderConfigs());
+    assertEquals("", response.getPageToken());
+  }
+
+  @Test
+  public void testEmptyTenantList() throws Exception {
+    ListOidcProviderConfigsResponse response =
+        new ListOidcProviderConfigsResponse(ImmutableList.<OidcProviderConfig>of(), "PAGE_TOKEN");
+
+    assertEquals(0, response.getProviderConfigs().size());
+    assertFalse(response.hasProviderConfigs());
+  }
+
+  @Test
+  public void testDeserialization() throws Exception {
+    String json = JSON_FACTORY.toString(
+        ImmutableMap.of(
+          "oauthIdpConfigs", ImmutableList.of(
+            ImmutableMap.of("name", "projects/projectId/oauthIdpConfigs/oidc.provider-id-1"),
+            ImmutableMap.of("name", "projects/projectId/oauthIdpConfigs/oidc.provider-id-2")),
+          "nextPageToken", "PAGE_TOKEN"));
+    ListOidcProviderConfigsResponse response =
+        JSON_FACTORY.fromString(json, ListOidcProviderConfigsResponse.class);
+
+    assertEquals(2, response.getProviderConfigs().size());
+    assertEquals("oidc.provider-id-1", response.getProviderConfigs().get(0).getProviderId());
+    assertEquals("oidc.provider-id-2", response.getProviderConfigs().get(1).getProviderId());
+    assertTrue(response.hasProviderConfigs());
+    assertEquals("PAGE_TOKEN", response.getPageToken());
+  }
+}
diff --git a/src/test/java/com/google/firebase/auth/internal/ListSamlProviderConfigsResponseTest.java b/src/test/java/com/google/firebase/auth/internal/ListSamlProviderConfigsResponseTest.java
new file mode 100644
index 0000000..6950fe3
--- /dev/null
+++ b/src/test/java/com/google/firebase/auth/internal/ListSamlProviderConfigsResponseTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.firebase.auth.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.api.client.googleapis.util.Utils;
+import com.google.api.client.json.JsonFactory;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.firebase.auth.SamlProviderConfig;
+
+import org.junit.Test;
+
+public class ListSamlProviderConfigsResponseTest {
+
+  private static final JsonFactory JSON_FACTORY = Utils.getDefaultJsonFactory();
+
+  @Test
+  public void testDefaultValues() throws Exception {
+    ListSamlProviderConfigsResponse response = new ListSamlProviderConfigsResponse();
+
+    assertEquals(0, response.getProviderConfigs().size());
+    assertFalse(response.hasProviderConfigs());
+    assertEquals("", response.getPageToken());
+  }
+
+  @Test
+  public void testEmptyTenantList() throws Exception {
+    ListSamlProviderConfigsResponse response =
+        new ListSamlProviderConfigsResponse(ImmutableList.<SamlProviderConfig>of(), "PAGE_TOKEN");
+
+    assertEquals(0, response.getProviderConfigs().size());
+    assertFalse(response.hasProviderConfigs());
+  }
+
+  @Test
+  public void testDeserialization() throws Exception {
+    String json = JSON_FACTORY.toString(
+        ImmutableMap.of(
+          "inboundSamlConfigs", ImmutableList.of(
+            ImmutableMap.of("name", "projects/projectId/inboundSamlConfigs/saml.provider-id-1"),
+            ImmutableMap.of("name", "projects/projectId/inboundSamlConfigs/saml.provider-id-2")),
+          "nextPageToken", "PAGE_TOKEN"));
+    ListSamlProviderConfigsResponse response =
+        JSON_FACTORY.fromString(json, ListSamlProviderConfigsResponse.class);
+
+    assertEquals(2, response.getProviderConfigs().size());
+    assertEquals("saml.provider-id-1", response.getProviderConfigs().get(0).getProviderId());
+    assertEquals("saml.provider-id-2", response.getProviderConfigs().get(1).getProviderId());
+    assertTrue(response.hasProviderConfigs());
+    assertEquals("PAGE_TOKEN", response.getPageToken());
+  }
+}
diff --git a/src/test/java/com/google/firebase/auth/internal/ListTenantsResponseTest.java b/src/test/java/com/google/firebase/auth/internal/ListTenantsResponseTest.java
new file mode 100644
index 0000000..7d65966
--- /dev/null
+++ b/src/test/java/com/google/firebase/auth/internal/ListTenantsResponseTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.firebase.auth.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.api.client.googleapis.util.Utils;
+import com.google.api.client.json.JsonFactory;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.firebase.auth.multitenancy.Tenant;
+
+import org.junit.Test;
+
+public class ListTenantsResponseTest {
+
+  private static final JsonFactory JSON_FACTORY = Utils.getDefaultJsonFactory();
+
+  @Test
+  public void testDefaultValues() throws Exception {
+    ListTenantsResponse response = new ListTenantsResponse();
+
+    assertEquals(0, response.getTenants().size());
+    assertFalse(response.hasTenants());
+    assertEquals("", response.getPageToken());
+  }
+
+  @Test
+  public void testEmptyTenantList() throws Exception {
+    ListTenantsResponse response =
+        new ListTenantsResponse(ImmutableList.<Tenant>of(), "PAGE_TOKEN");
+
+    assertEquals(0, response.getTenants().size());
+    assertFalse(response.hasTenants());
+  }
+
+  @Test
+  public void testDeserialization() throws Exception {
+    String json = JSON_FACTORY.toString(
+        ImmutableMap.of(
+          "tenants", ImmutableList.of(
+            ImmutableMap.of("name", "projects/project-id/resource/TENANT_1"),
+            ImmutableMap.of("name", "projects/project-id/resource/TENANT_2")),
+          "pageToken", "PAGE_TOKEN"));
+    ListTenantsResponse response = JSON_FACTORY.fromString(json, ListTenantsResponse.class);
+
+    assertEquals(2, response.getTenants().size());
+    assertEquals("TENANT_1", response.getTenants().get(0).getTenantId());
+    assertEquals("TENANT_2", response.getTenants().get(1).getTenantId());
+    assertTrue(response.hasTenants());
+    assertEquals("PAGE_TOKEN", response.getPageToken());
+  }
+}
diff --git a/src/test/java/com/google/firebase/auth/multitenancy/ListTenantsPageTest.java b/src/test/java/com/google/firebase/auth/multitenancy/ListTenantsPageTest.java
index 99a9786..1083059 100644
--- a/src/test/java/com/google/firebase/auth/multitenancy/ListTenantsPageTest.java
+++ b/src/test/java/com/google/firebase/auth/multitenancy/ListTenantsPageTest.java
@@ -27,8 +27,6 @@ import com.google.api.client.googleapis.util.Utils;
 import com.google.common.collect.ImmutableList;
 import com.google.firebase.auth.FirebaseAuthException;
 import com.google.firebase.auth.internal.ListTenantsResponse;
-import com.google.firebase.auth.multitenancy.ListTenantsPage;
-import com.google.firebase.auth.multitenancy.Tenant;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -328,7 +326,7 @@ public class ListTenantsPageTest {
   private static class TestTenantSource implements ListTenantsPage.TenantSource {
 
     private ListTenantsResponse response;
-    private List<String> calls = new ArrayList<>();
+    private final List<String> calls = new ArrayList<>();
 
     TestTenantSource(int tenantCount) throws IOException {
       ImmutableList.Builder<Tenant> tenants = ImmutableList.builder();
diff --git a/src/test/java/com/google/firebase/auth/multitenancy/TenantTest.java b/src/test/java/com/google/firebase/auth/multitenancy/TenantTest.java
index 39b7de3..7ea4f25 100644
--- a/src/test/java/com/google/firebase/auth/multitenancy/TenantTest.java
+++ b/src/test/java/com/google/firebase/auth/multitenancy/TenantTest.java
@@ -18,21 +18,19 @@ package com.google.firebase.auth.multitenancy;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import com.google.api.client.googleapis.util.Utils;
 import com.google.api.client.json.JsonFactory;
-import com.google.firebase.auth.multitenancy.Tenant;
 import java.io.IOException;
 import java.util.Map;
 import org.junit.Test;
 
 public class TenantTest {
 
-  private static final JsonFactory jsonFactory = Utils.getDefaultJsonFactory();
+  private static final JsonFactory JSON_FACTORY = Utils.getDefaultJsonFactory();
 
-  private static final String TENANT_JSON_STRING =
+  private static final String TENANT_JSON_STRING = 
       "{"
         + "\"name\":\"projects/project-id/resource/TENANT_ID\","
         + "\"displayName\":\"DISPLAY_NAME\","
@@ -42,7 +40,7 @@ public class TenantTest {
 
   @Test
   public void testJsonDeserialization() throws IOException {
-    Tenant tenant = jsonFactory.fromString(TENANT_JSON_STRING, Tenant.class);
+    Tenant tenant = JSON_FACTORY.fromString(TENANT_JSON_STRING, Tenant.class);
 
     assertEquals(tenant.getTenantId(), "TENANT_ID");
     assertEquals(tenant.getDisplayName(), "DISPLAY_NAME");
@@ -52,7 +50,7 @@ public class TenantTest {
 
   @Test
   public void testUpdateRequestFromTenant() throws IOException {
-    Tenant tenant = jsonFactory.fromString(TENANT_JSON_STRING, Tenant.class);
+    Tenant tenant = JSON_FACTORY.fromString(TENANT_JSON_STRING, Tenant.class);
 
     Tenant.UpdateRequest updateRequest = tenant.updateRequest();