88 votes

JUnit : utilisation d'un constructeur au lieu de @Before

J'utilise JUnit 4. Je ne vois pas la différence entre initialiser dans le constructeur ou utiliser une fonction init dédiée annotée par @Before . Cela signifie-t-il que je ne dois pas m'en préoccuper ?

Y a-t-il un cas où @Before donne plus qu'une simple initialisation dans le constructeur ?

1 votes

0 votes

0 votes

Tu es sûr que tu veux dire @Before pas @BeforeClass ? Vérifiez la différence aquí .

99voto

Péter Török Points 72981

Non, l'utilisation du constructeur pour initialiser votre montage de test JUnit est techniquement égale à l'utilisation de la fonction @Before (en raison du fait que JUnit crée une nouvelle instance de la classe testing pour chaque @Test ). La seule différence (connotative) est qu'elle rompt la symétrie entre @Before y @After ce qui peut être déroutant pour certains. À mon avis, il est préférable d'adhérer aux conventions (ce qui consiste à utiliser @Before ).

Notez également qu'avant JUnit 4 et les annotations, il existait des outils dédiés à l'analyse des données. setUp() y tearDown() les méthodes - le @Before y @After Les annotations remplacent ces dernières, mais préservent la logique sous-jacente. Ainsi, l'utilisation des annotations facilite également la vie de ceux qui migrent de JUnit 3 ou de versions antérieures.

Différences notables

Plus de détails dans les commentaires :

  • @Before permet de remplacer le comportement de la classe mère, les constructeurs vous obligent à appeler les constructeurs de la classe mère.
  • Le constructeur exécute avant et les constructeurs de sous-classes @Rule méthodes, @Before exécute après tout cela
  • Exceptions pendant @Before cause @After méthodes à appeler, les exceptions dans le constructeur ne sont pas

2 votes

@Before n'est pas appelé plusieurs fois ? (avant chaque méthode de test ?)

3 votes

@Sylvain, étant donné que JUnit crée une nouvelle instance de classe de test pour chaque méthode de test, le constructeur et l'instance de la classe de test ne sont pas utilisés. @Before est appelé exactement le même nombre de fois.

9 votes

Entre-temps, j'ai lu une différence importante : si une L'exception est levée dans le constructeur alors il n'y aura pas d'objet à exécuter @After sur. J'ai donc continué à utiliser les annotations et à ne garder que le constructeur minimal.

31voto

HopefullyHelpful Points 121

Il est plus logique d'utiliser @Before dans certains cas, car il est appelé APRÈS le constructeur de la classe. Cette différence est importante lorsque vous utilisez un framework mock comme Mockito avec les annotations @Mock, car votre méthode @Before sera appelée après l'initialisation des mocks. Vous pouvez alors utiliser vos mocks pour fournir des arguments de constructeur à la classe testée.

Je trouve que c'est un modèle très courant dans mes tests unitaires lorsqu'on utilise des beans en collaboration.

Voici un exemple (certes artificiel) :

@RunWith(MockitoJUnitRunner.class)
public class CalculatorTest {
    @Mock Adder adder;
    @Mock Subtractor subtractor;
    @Mock Divider divider;
    @Mock Multiplier multiplier;

    Calculator calculator;

    @Before
    public void setUp() {
        calculator = new Calculator(adder,subtractor,divider,multiplier);
    }

    @Test
    public void testAdd() {
        BigDecimal value = calculator.add(2,2);
        verify(adder).add(eq(2),eq(2));
    }
}

1 votes

Pourquoi ne pouvez-vous pas faire la même chose dans un constructeur ? Dans un constructeur, il suffit d'initialiser la calculatrice avec tous les objets fantaisie que le responsable des tests aurait dû initialiser en premier.

0 votes

De plus, vous avez défini ces Mocks comme étant @Nonnull. Vous avez besoin d'un constructeur pour corriger cela. Une méthode setUp() ne suffira pas, car vous pouvez instancier la classe CalculatorTest dans un autre test, ce qui provoquera des NPE.

14voto

Derek Mahar Points 7125

Je préfère utiliser les constructeurs pour initialiser mes objets de test parce que cela me permet de faire tous les membres final de sorte que l'IDE ou le compilateur me dise quand les Constructeur a oublié d'initialiser un membre et d'empêcher une autre méthode de les paramétrer.

IMHO, @Before viole l'une des conventions Java les plus importantes, celle de s'appuyer sur le constructeur pour inaliser complètement les objets !

JUnit 5 a également un meilleur support pour l'injection de constructeur.

5voto

thSoft Points 5513

Je préfère déclarer mes fixtures comme final et les initialiser en ligne ou dans le constructeur pour ne pas oublier de les initialiser ! Cependant, comme les exceptions lancées dans @Before sont traitées de manière plus conviviale, j'initialise généralement l'objet testé dans @Before.

1voto

oers Points 9920

@Before est invoqué avant tout @Test et pas seulement une fois par classe de test.
Ceci peut être utilisé pour réinitialiser/initialiser les données pour chaque test spécifique (comme réinitialiser les variables à une valeur spécifique, etc.).

De la même manière, @After peut être utilisé pour nettoyer le code après l'exécution d'une méthode @Test.

Ver: http://junit.sourceforge.net/javadoc/org/junit/Before.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X