@Test
  public void exploreExternalCatalog_ListDatabasesException() {
    createTable();
    ServerCatalog originalCatalog = catalogManager().getServerCatalog(TEST_CATALOG_NAME);

    // test list tables
    List<TableRuntimeMeta> tableRuntimeMetaListAfterAddTable = persistency.getTableRuntimeMetas();
    Assert.assertEquals(1, tableRuntimeMetaListAfterAddTable.size());

    MockitoAnnotations.openMocks(this);
    when(externalCatalog.name()).thenReturn(TEST_CATALOG_NAME);
    when(externalCatalog.toString()).thenReturn(originalCatalog.toString());
    when(externalCatalog.getMetadata()).thenReturn(originalCatalog.getMetadata());
    when(externalCatalog.listDatabases()).thenThrow(new RuntimeException("List databases error"));

    // This should throw an exception
    Assert.assertThrows(
        "List databases error",
        RuntimeException.class,
        () -> tableService().exploreExternalCatalog(externalCatalog));

    verify(externalCatalog, times(1)).listDatabases();

    // test tableRuntime not removed
    List<TableRuntimeMeta> tableRuntimeMetaListAfterExploreCatalog =
        persistency.getTableRuntimeMetas();
    Assert.assertEquals(1, tableRuntimeMetaListAfterExploreCatalog.size());

    dropTable();
    dropDatabase();
  }
Test synchronization in the anomaly scenario where the tableIdentifier is remained in
persistence and the tableRuntime is remained in memory but iceberg table does not exist.
amoro-ams/src/test/java/org/apache/amoro/server/table/TestSyncTableOfExternalCatalog.java