JUnit: using constructor instead of @Before

前端 未结 8 789
旧巷少年郎
旧巷少年郎 2020-12-04 14:10

I\'m using JUnit 4. I can\'t see the difference between initializing in the constructor or using a dedicated init function annotated by @Before. Does this mean

相关标签:
8条回答
  • 2020-12-04 14:38

    There is no difference except that the constructor is the only method ehere can initialize the @Rule objects:

    public class TestClass {
    
        @Rule
        public SomeRule rule;
    
        public TestClass() {
            // code to initialize the rule field
            conf = new RuleConf()
            rule = new SomeRule(conf)
        }
    }
    
    0 讨论(0)
  • 2020-12-04 14:39

    @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));
        }
    }
    
    0 讨论(0)
  • 2020-12-04 14:39

    I prefer to declare my fixtures as final and initialize them inline or in the constructor so I don't forget to initialize them! However, since exceptions thrown in @Before are handled in a more user-friendly way, I usually initialize the object under test in @Before.

    0 讨论(0)
  • 2020-12-04 14:39

    @Before does make sense to use for several reasons. It makes your test code more readable. It matches @After annotation which is responsible for releasing used resources and is a counterpart of the @BeforeClass annotation.

    0 讨论(0)
  • 2020-12-04 14:46

    Quote from http://etutorials.org/Programming/Java+extreme+programming/Chapter+4.+JUnit/4.6+Set+Up+and+Tear+Down/

    You may be wondering why you should write a setUp( ) method instead of simply initializing fields in a test case's constructor. After all, since a new instance of the test case is created for each of its test methods, the constructor is always called before setUp( ). In a vast majority of cases, you can use the constructor instead of setUp( ) without any side effects.

    In cases where your test case is part of a deeper inheritance hierarchy, you may wish to postpone object initialization until instances of derived classes are fully constructed. This is a good technical reason why you might want to use setUp( ) instead of a constructor for initialization. Using setUp( ) and tearDown( ) is also good for documentation purposes, simply because it may make the code easier to read.

    0 讨论(0)
  • 2020-12-04 14:57

    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
    0 讨论(0)
提交回复
热议问题