Mocker les appels à System.exit, System.out, ...

05 Jun 2014

Il est difficile de tester du code faisant appel à java.lang.System. En effet si le code à tester fait un appel à System.exit(int), la JVM s'arrête avec notre JUnit...

Il existe un ensemble de JUnit rules permettant de tester quand même. Il est donc nécessaire d'utiliser une version de JUnit supérieure à 4.7.

Je ne détaillerai que l'utilisation pour les appels à System.exit, System.out et System.err. La librairie utilisée permet plus de chose et la documention est plutôt bien fournie Github

Un projet exemple se trouve ici.

Dépendance maven

La dépendance maven à utiliser est :

<dependency>
 <groupId>com.github.stefanbirkner</groupId>
 <artifactId>system-rules</artifactId>
 <version>1.3.0</version>
 <scope>test</scope>
</dependency>

Mocker System.exit

Pour mocker un appel à System.exit, il suffit de déclarer la Rule :

public class MaClasseTest {
 @Rule
 public final ExpectedSystemExit m_exit = ExpectedSystemExit.none();
...
}

Ensuite si on doit s'attendre à un appel à System.exit, dans la méthode de test on utilise

@Test
public void testExit() {
 m_exit.expectSystemExitWithStatus(5);
 ...
}

Dans l'exemple ci-dessus, le test est OK si System.exit(5) a été appelé.

Cependant avec l'utilisation de cette rule, il n'est plus possible d'effectuer des vérifications (Assert) au retour de la méthode à tester. Cependant la Rule permet de definir une callback qui sera appelé à la fin du test nous permettant de faire des vérifications supplémentaire. On la définit avec checkAssertionAfterwards()

@Test
public void testExit() {
 m_exit.expectSystemExitWithStatus(5);
 m_exit.checkAssertionAfterwards(new Assertion() {
  public void checkAssertion() throws Exception {
   Assert.assertTrue(m_aTester.isSortie());
  }
 }); 
 m_aTester.exit(true);
}

Mocker System.out

Pour contrôler le contenu envoyé sur la sortie standart avec System.out, il suffit de déclarer la Rule :

public class MaClasseTest {
 @Rule
 public final StandardOutputStreamLog m_out = new StandardOutputStreamLog();
...
}

Ensuite à la fin du test, on peut récupérer le contenu envoyé sur la sortie standart avec

m_out.getLog()

Mocker System.err

Pour contrôler le contenu envoyé sur la sortie erreur avec System.err, il suffit de déclarer la Rule :

public class MaClasseTest {
 @Rule
 public final StandardErrorStreamLog m_err = new StandardErrorStreamLog();
...
}

Ensuite à la fin du test, on peut récupérer le contenu envoyé sur la sortie erreur avec

m_err.getLog()