J'utilise JUnit 4. Je ne vois pas la différence entre l'initialisation dans le constructeur et l'utilisation d'une fonction init dédiée annotée par @Before
. Est-ce que cela signifie que je n'ai pas à m'inquiéter?
Existe-t-il un cas où @Before
donne plus que l'initialisation dans le constructeur?
Non, utiliser le constructeur pour initialiser votre appareil de test JUnit est techniquement équivalent à utiliser la méthode @Before
(en raison du fait que JUnit crée une nouvelle instance de la classe de test pour chaque @Test
). La seule différence (connotative) est que cela brise la symétrie entre @Before
et @After
, ce qui peut être déroutant pour certains. IMHO il est préférable de respecter les conventions (qui utilise @Before
).
Notez également qu'avant JUnit 4 et les annotations, il existait des méthodes dédiées setUp()
et tearDown()
; les annotations @Before
et @After
les remplacent, tout en préservant la logique sous-jacente. Par conséquent, l’utilisation des annotations facilite également la tâche de ceux qui migrent depuis JUnit 3 ou des versions antérieures.
Plus de détails à partir des commentaires:
@Before
permet de redéfinir le comportement de la classe parent, les constructeurs vous forçant à appeler les constructeurs de la classe parent@Rule
, @Before
exécute after tous ceux@Before
entraînent l'appel de méthodes @After
, les exceptions dans le constructeur ne le font pas@Before est plus logique à utiliser dans certains cas car il est appelé APRÈS le constructeur de la classe. Cette différence est importante lorsque vous utilisez un framework fictif tel que Mockito avec des annotations @Mock, car votre méthode @Before sera appelée après l'initialisation des simulations. Vous pouvez ensuite utiliser vos modèles pour fournir des arguments de constructeur à la classe sous test.
Je trouve ce schéma très courant dans mes tests unitaires lors de l’utilisation de beans collaborateurs.
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));
}
}
Je préfère utiliser des constructeurs pour initialiser mes objets de test, car cela me permet de rendre tous les membres final
afin que le IDE ou le compilateur me dise quand le constructeur a oublié d'initialiser un membre et empêche une autre méthode de les mettre.
IMHO, @Before
enfreint l'une des conventions les plus importantes de Java, celle de s'appuyer sur le constructeur pour initaliser complètement les objets!
Je préfère déclarer mes appareils comme finaux et les initialiser en ligne ou dans le constructeur, alors je n'oublie pas de les initialiser! Cependant, comme les exceptions générées dans @Before sont gérées de manière plus conviviale, j’initialise habituellement l’objet à tester dans @Before.
Il y a une chose que constructeur peut archiver mais pas @Avant .
Vous devez utiliser un constructeur lorsque vous devez initialiser les champs définis dans la classe parente. Par exemple:
abstract class AbstractIT {
int fieldAssignedInSubClass;
public AbstractIT(int fieldAssignedInSubClass) {
this.fieldAssignedInSubClass= fieldAssignedInSubClass;
}
@Before
void before() {
// comsume fieldAssignedInSubClass
}
}
public class ChildIT extends AbstractIT{
public ChildIT() {
// assign fieldAssignedInSubClass by constructor
super(5566);
}
@Before
void before() {
// you cannot assign fieldAssignedInSubClass by a @Before method
}
}
@Before est invoqué avant tout @Test et pas seulement une fois par Test-Class.
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.).
Dans le même mode, @After peut être utilisé pour nettoyer le code après l'exécution d'une méthode @Test.
Voir: http://junit.sourceforge.net/javadoc/org/junit/Before.html
Citation de http://etutorials.org/Programming/Java+extreme+programming/Chapter+4.+JUnit/4.6+Set+Up+and+Tear+Down/
Vous vous demandez peut-être pourquoi vous devriez écrire une méthode setUp () au lieu de initialiser simplement les champs dans le constructeur d'un cas de test. Après tout, puisqu’une nouvelle instance du scénario de test est créée pour chacun de ses tests méthodes, le constructeur est toujours appelé avant setUp (). Dans un vaste Dans la majorité des cas, vous pouvez utiliser le constructeur à la place de setUp () sans aucun effet secondaire.
Dans les cas où votre cas de test fait partie d'un héritage plus profond hiérarchie, vous souhaiterez peut-être différer l’initialisation de l’objet jusqu’à les instances de classes dérivées sont entièrement construites. C'est un bon raison technique pour laquelle vous voudrez peut-être utiliser setUp () au lieu de constructeur pour l'initialisation. Utiliser setUp () et tearDown () est aussi bon pour la documentation, simplement parce que cela peut rendre le code plus facile à lire.
@Before
est logique à utiliser pour plusieurs raisons. Cela rend votre code de test plus lisible. Il correspond à l'annotation @After
qui est responsable de la libération des ressources utilisées et est l'homologue de l'annotation @BeforeClass
.
Il n'y a pas de différence sauf que le constructeur est la seule méthode permettant d'initialiser les objets @Rule:
public class TestClass {
@Rule
public SomeRule rule;
public TestClass() {
// code to initialize the rule field
conf = new RuleConf()
rule = new SomeRule(conf)
}
}