Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Junit - Multiple @Before vs. one @Before split up into methods

Tags:

java

junit

In a unit test, I need to perform a quite complex setup (this may be a code smell but this is not what this question is about :-)). What I'm interested in is if it is better to have multiple @Before methods performing the setup or just one, which calls helper methods to perform the initialization.

E.g.

@Before public void setUpClientStub() {  }  @Before public void setUpObjectUnderTest() {  } 

vs.

@Before public void setUp() {     setUpClientStub();     setUpObjectUnderTest(); } 
like image 428
helpermethod Avatar asked Feb 03 '12 15:02

helpermethod


People also ask

Can we have two @before in JUnit?

The JUnit Team therefore recommends that developers declare at most one @BeforeEach method and at most one @AfterEach method per test class or test interface unless there are no dependencies between the @BeforeEach methods or between the @AfterEach methods.

What is the difference between @BeforeClass and @before in JUnit?

The code marked @Before is executed before each test, while @BeforeClass runs once before the entire test fixture. If your test class has ten tests, @Before code will be executed ten times, but @BeforeClass will be executed only once.

In what order is multiple @before annotated methods run?

2. In what order is multiple @Before annotated methods run? Explanation: It is not certain which @Before annotated method will run first as all run randomly. 3.

Does @before run before each test?

Methods annotated with the @Before annotation are run before each test. This is useful when we want to execute some common code before running a test. Notice that we also added another method annotated with @After in order to clear the list after the execution of each test.


2 Answers

As has been said in other responses, the order in which JUnit finds methods is not guaranteed, so the execution order of @Before methods can't be guaranteed. The same is true of @Rule, it suffers from the same lack of guarantee. If this will always be the same code, then there isn't any point in splitting into two methods.

If you do have two methods, and more importantly, if you wish to use them from multiple places, then you can combine rules using a RuleChain, which was introduced in 4.10. This allows the specific ordering of rules, such as:

public static class UseRuleChain {   @Rule   public TestRule chain= RuleChain                .outerRule(new LoggingRule("outer rule"))                .around(new LoggingRule("middle rule"))                .around(new LoggingRule("inner rule"));    @Test   public void example() {       assertTrue(true);   } } 

This produces:

starting outer rule starting middle rule starting inner rule finished inner rule finished middle rule finished outer rule 

So you can either upgrade to 4.10 or just steal the class.

In your case, you could define two rules, one for client setup and one for object, and combine them in a RuleChain. Using ExternalResource.

public static class UsesExternalResource {   private TestRule clientRule = new ExternalResource() {       @Override       protected void before() throws Throwable {         setupClientCode();       };        @Override       protected void after() {         tearDownClientCode()     };   };    @Rule public TestRule chain = RuleChain                    .outerRule(clientRule)                    .around(objectRule); } 

So you'll have the following execution order:

clientRule.before() objectRule.before() the test objectRule.after() clientRule.after() 
like image 194
Matthew Farwell Avatar answered Sep 23 '22 12:09

Matthew Farwell


I would do the latter. AFAIK, there is no way to guarantee order of @Before annotated setup methods.

like image 25
hvgotcodes Avatar answered Sep 22 '22 12:09

hvgotcodes