13

Why the @BeforeClass method in JUnit is static whereas in TestNG its non-static? TestNG was developed as an improvement over JUnit, so why did they choose this way of implementation?

Since @BeforeClass runs only once, so making it static makes more sense than making it non static. Also in TestNG, on which instance the @BeforeClass method is called? Can someone cite an example for better understanding?

dejavu
  • 3,236
  • 7
  • 35
  • 60
  • Note that TestNG's annotations were developed *before* JUnit's; TestNG was an improvement over JUnit `v3.*`, but they seem roughly equivalent now that JUnit has annotations as well (at JUnit `v4.*`). – jpaugh Dec 23 '15 at 15:47

2 Answers2

16

The main difference between JUnit and TestNG is the test class instantiation. JUnit always creates a new instance of the test class for each test method run. TestNG only creates one test class instance and then runs all test methods of this instance.

The JUnit approach guarantees the independency of all test methods. It just does not matter, in which order they run. Additionally, all instance fields are always setup the same for each test method. Initializing data, that is common for all test methods, must take place at the class level, thus it must be static. This is the reason, why the @BeforeClass method must be static.

The TestNG approch does not guarante the independency. In fact, you cannot use an instance field in the same manner as in JUnit tests. If you change such a field in one test method, the changed value is still observabl in another test method. However, this behavior has also an advantage: Sometimes there are dependencies between some test methods. With TestNG, a tester can express them.

Because of the one-instance-approach of TestNG, the @BeforeClass setup can also be a non-static method, but it is still run only once. It was a design decision, but testers using TestNG must be aware of that.

Seelenvirtuose
  • 20,273
  • 6
  • 37
  • 66
  • 3
    The only difference is that in JUnit you can use instance fields and stay isolated, in TestNG you cannot. If you want to ruin the isolation, you can still use static field in JUnit... or any in TestNG. No TestNG users have problems with this if they want to keep the tests isolated. Problems come when they want to make dependent tests (whatever the reason), TestNG supports it better, although you have to know the cost. Think of TestNG test as a servlet - you can prepare stuff there, but it's shared. Is it bad or good? It's just a fact. – virgo47 Jul 25 '14 at 09:46
  • @virgo47 - Is it okay to initialize non-static class variables inside "@BeforeClass" ? – MasterJoe Jan 03 '19 at 19:50
  • Well, you should always consult documentation and make your own mind about it - but if you believe me; for non-static it is both in JUnit and TestNG. :-) (The difference is with static fields.) Happy New Year. – virgo47 Jan 04 '19 at 21:56
1

Making a method static or non-static has nothing to do with being able to invoke that method only once at the beginning. You can call a static method as many times as you want. You can call a non-static method exactly one. There is no necessary correlation between the two : being static and invoking once. At least, I am not aware of any direct consequence of making a method static which enables it to be invoked exactly once. static is rightly associated with single class, but not with single invocation.

Making a method static prevents it from accessing non-static members of the class. But with having a non-static @BeforeClass method, you can also access non-static members, there by giving you more scope to access class variables. Perhaps this is the reason why testng removed the restriction of @BeforeClass method being static.

Shiva Kumar
  • 3,111
  • 1
  • 26
  • 34
  • My question was not related to invoking it once or more than once. '@BeforeClass' is executed at the start of test case (not each test case), so it cannot be associated with any instance. Junit creates a new instance of class for every test method. Since '@beforeclass' is non static in testNG, it has to be associated with a instance. Does that mean that in testNG, @beforeclass is executed for every test? If not, then how it works? – dejavu Dec 05 '13 at 08:36
  • @BeforeClass is just an annotation. The junit runner just needs to get list of all the methods annotated with this method and execute them once before executing each test. In testng too @BeforeClass is executed only once for the entire test class. To my knowledge Junit collects all the methods annotated with `@Test` and calls them reflectively. I am not sure if junit really creates a new instance for every test case. – Shiva Kumar Dec 05 '13 at 08:57
  • It creates a new instance for every test case : http://stackoverflow.com/a/3353183/808203 – dejavu Dec 05 '13 at 08:59