web-dev-qa-db-fra.com

L'essai avec ressources de Java détecte-t-il des erreurs ou simplement des exceptions?

J'ai quelques tests junit qui créent des ressources qui devraient également être fermées.

Une façon d'implémenter cette logique consiste à utiliser le @Before et @After approche.

Ce que j'ai fait était d'encapsuler la création dans une classe utilitaire à réutiliser. Par exemple:

class UserCreatorTestUtil implements AutoClosable {
  User create() {...}
  void close() {...}
}

Le but est que l'objet se ferme lui-même, plutôt que d'avoir à se rappeler de le fermer dans @After.

L'utilisation doit être:

@Test
void test() {
  try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
    User user = userCreatorTestUtil.create();
    // Do some stuff regarding the user's phone
    Assert.assertEquals("123456789", user.getPhone());
  }
}

Le problème est que le mot clé assert de junit envoie un Error - pas Exception.

L'essai avec ressource "attraper" le Error et invoquer la méthode close?

* Impossible de trouver la réponse dans la documentation try-with-resources .

53
AlikElzin-kilaka

Il ne fait rien catch. Mais il finally ferme toutes les ressources.

finally blocs sont exécutés même lorsqu'une erreur est levée .

75
Thilo

Le pseudo-code d'une instruction de base try-with-resources est (cf Java Language Specification §14.20.3.1 ):

final VariableModifiers_minus_final R Identifier = Expression;
Throwable #primaryExc = null;

try ResourceSpecification_tail
    Block
catch (Throwable #t) {
    #primaryExc = #t;
    throw #t;
} finally {
    if (Identifier != null) {
        if (#primaryExc != null) {
            try {
                Identifier.close();
            } catch (Throwable #suppressedExc) {
                #primaryExc.addSuppressed(#suppressedExc);
            }
        } else {
            Identifier.close();
        }
    }
}

Comme vous pouvez le voir, il capture Throwable pas Exception qui inclut Error mais uniquement pour obtenir l'exception principale afin d'ajouter comme exceptions supprimées toutes les exceptions qui se sont produites lors de la fermeture des ressources.

Vous pouvez également remarquer que vos ressources sont fermées dans le bloc finally ce qui signifie que elles seront fermées quoi qu'il arrive (sauf en cas de une System.exit bien sûr, car il met fin à la Java virtuelle) en cours d'exécution, même si un Error ou une sous-classe de Throwable est lancé.

37
Nicolas Filotto

L'essai avec les ressources n'attrape rien en soi.

Cependant, vous pouvez attacher un bloc catch à la fin du bloc try-with-resources, pour intercepter les types de Throwable que vous aimez:

try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
  // ... Whatever
} catch (RuntimeException e) {
  // Handle e.
} catch (Exception | Throwable t) {
  // Handle t.
}
13
Andy Turner

L'idée derrière try-with-resources Est de s'assurer que les ressources doivent être fermées.

Le problème avec les instructions try-catch-finally Conventionnelles est que supposons que votre bloc try lève une exception; maintenant, vous gérerez généralement cette exception dans le bloc finally.

Supposons maintenant qu'une exception se produit également dans le bloc enfin. Dans un tel cas, l'exception levée par try catch est perdue et l'exception générée dans le bloc finally est propagée.

try {
    // use something that's using resource
    // e.g., streams
} catch(IOException e) {
   // handle 
} finally {
    stream.close();
    //if any exception occurs in the above line, than that exception
    //will be propagated and the original exception that occurred
    //in try block is lost.
}

Dans try-with-resources, La méthode close() de la ressource sera automatiquement appelée, et si la close() lève une exception, le reste de la finally isn ' t atteint et l'exception d'origine est perdue.

Comparez cela avec ceci:

try (InputStream inputStream= new FileInputStream("C://test.txt")){
    // ... use stream
} catch(IOException e) {
   // handle exception
}

dans l'extrait de code ci-dessus, la méthode close() est automatiquement appelée et si cette méthode close() a également généré une exception, cette exception sera automatiquement supprimée.

Voir aussi: Java Language Specification 14.20.

9
Raman Sahasi

Idée fausse de votre côté: essayer avec des ressources ne pas faire un catch.

Il fait un final enfin , donc le genre de "problème" n'a pas d'importance.

Voir JLS pour plus d'informations!

5
GhostCat