JUnit: using constructor instead of @Before

No, using the constructor to initialize your JUnit test fixture is technically equal to using the @Before method (due to the fact that JUnit creates a new instance of the testing class for each @Test). The only (connotational) difference is that it breaks the symmetry between @Before and @After, which may be confusing for some. IMHO it is better to adhere to conventions (which is using @Before).

Note also that prior to JUnit 4 and annotations, there were dedicated setUp() and tearDown() methods - the @Before and @After annotations replace these, but preserve the underlying logic. So using the annotations also makes life easier for someone migrating from JUnit 3 or earlier versions.

Notable differences

More details from comments:

  • @Before allows overriding parent class behavior, constructors force you to call parent class constructors
  • The constructor runs before subclass constructors and @Rule methods, @Before runs after all of those
  • Exceptions during @Before cause @After methods to be called, Exceptions in constructor don't

@Before makes more sense to use in certain cases because it gets called AFTER the constructor for the class. This difference is important when you're using a mock framework like Mockito with @Mock annotations, because your @Before method will be called after the mocks are initialized. Then you can use your mocks to provide constructor arguments to the class under test.

I find this to be a very common pattern in my unit tests when using collaborating beans.

Here's an (admittedly contrived) example:

@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));
    }
}

I prefer to use constructors to initialize my test objects because it allows me to make all the members final so that the IDE or compiler will tell me when the constructor forgot to initialize a member and prevent another method from setting them.

IMHO, @Before violates one of the most important Java conventions, that of relying on the constructor to completely initalize objects!

JUnit 5 also has better support for constructor injection.