#BeforeClass annotation: Junit vs TestNG - java

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?

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.

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.

Related

Why methods annotated with #BeforeAll and #AfterAll should be static in JUnit 5?

I know that methods annotated with #BeforeAll and #AfterAll JUnit 5 annotations should be static unless TestInstance.Lifecycle.PER_CLASS is used.
What I can't understand is why JUnit 5 imposes such limitations? If it is allowed with PER_CLASS lifecycle, what changes drastically when using PER_METHOD?
Thanks in advance.
When you use PER_METHOD, a new instance of the test class is created for each test method. Methods annotated with #BeforeAll would need to be called before any instance is created. Likewise, #AfterAll needs to be called after all tests are done, and therefore no instance is available anymore. That lack of instances means these methods need to be static.

Anyway to create a Test Helper class that creates mocks?

In my testing of a legacy system, I have found myself having to mock similar classes for different parts of the system I'm increasing test coverage for. I would like to create a helper class for my tests that could call a method that would set up particular mocks and their return values.
Here's an example of a method I have had to create a few times in multiple tests.
public void mockClassINeedToMockToReturn(Boolean bool){
mockStatic(classINeedToMock.class);
when(classINeedToMock.getSuccess(Mockito.any(someClass.class))).thenReturn(bool);
}
I have tried setting this up in a HelperTest.class (in the same project/folder as my tests) and it isn't working. I have included both the following Annotations in the class.
#RunWith(PowerMockRunner.class)
#PrepareForTest({classINeedToMock.class})
I have tried:
Using the methods statically and calling them in my tests. (does not mock)
Creating a HelperTest object and calling the method in my test. (still does not mock)
Having my tests Extend my HelperTest.class and calling the method from in my tests. (Still refuses to mock the class)
I'm sure this is something to do with the way the PowerMockRunner works. So is there a way to make this work? Or should I just come to terms with duplicating these methods throughout my project.
It's the little details.... When looking into it more I noticed the class I was mocking had 2 separate methods.
theClass.method(var1, var2);
theClass.method(var1, List<var2>);
One of my tests was calling the first method, the other was calling the second method. When I ran the second test (only having mocked the first method), it was calling the actual class because that method was not mocked.
After setting up the correct mock with the proper input parameters I could call the method statically and the mock would be created and used appropriately.

java - Allow extending static method in sub classes

Using JUnit all my runner classes implement a method that is annotated with
#BeforeClass
public static void setUp() throws Exception {}
There is a lot of mutual code.
I want to create a base runner that will hold all the base code and will allow sub classes to add more features.
This is all static. What is the best practice?
You should reconsider your design. The #BeforeClass annotation is intended to specify code that has to run exactly once for all tests. If you repeat the same code in multiple static methods annotated with #BeforeClass, in other words, execute the same action multiple times, it suggests that it is not the #BeforeClass semantic that you want.
Maybe you just want instance methods annotated with #Before
Otherwise, if it’s really about single time actions, just put a static method with the #BeforeClass annotation into the base class, and you’re done. The initialization of the subclass implies the initialization of the base class. The initialization of the base class will happen exactly once for all subclasses but that is what #BeforeClass is all about. As said, if you want an initialization once per subclass or once per test, it’s more likely that #Before is the feature you want.
Note further, that you can have code in static methods in a base class which is only executed when subclasses invoke it. Just place the code into a method without the #BeforeClass annotation. Then, methods in subclasses, having the annotation or not, may invoke the method of the base class. There is no need for an override relationship here.
As said; there is no "overriding" for static; and of course: static is by itself ... very often an indication for "design improvement required". Everybody who is writing serious unit tests knows that static things can make unit testing a night-mare. So we avoid static in our production code. But then, in our testing code, we just use it?!
And going one step further: some people claim that inheritance is not a good answer to "i have a lot of common code within my unit tests".
See here for example.
You could move the common code to a rule and reuse that rule in every test: https://github.com/junit-team/junit/wiki/Rules

How JUnit manages running #BeforeClass only once which is defined inside the test class

I very much understand what #BeforeClass is. It is executed once before JUnit test run is started & #Before method is executed before every test case.
My question is regarding a very old post by a very senior stackoverflow user (Péter Török
68.8k) Please refer [stackoverflow question]
[1]: JUnit: using constructor instead of #Before which was posted about 2 yrs ago but on JUnit4. so I think it is still valid and true.
Here he mentions
#Before is equivalent to constructor of test class
and
JUnit creates a new instance of the test class for each #Test,
So how does JUnit manage running #BeforeClass only once which is defined inside the test class?
Methods annotated with #BeforeClass must be static. JUnit doesn't need any instance of the test class to call it.
Well, jUnit could run the method annotated with #BeforeClass at time of class loading, that is like you would implement on your own with a static initializer.
You get also the hint that jUnit is doing something like this by the fact that #BeforeClass and #AfterClass annotated methods must be static.
That's because #BeforeClass has to be a static method. Once it is static, JUnit knows how to run it once.
Sometimes several tests need to share computationally expensive setup (like logging into a database). While this can compromise the independence of tests, sometimes it is a necessary optimization. Annotating a public static void no-arg method with #BeforeClass causes it to be run once before any of the test methods in the class. The #BeforeClass methods of superclasses will be run before those the current class. Static methods are not belongs to instances of the class. Those are properties of the class.

#BeforeClass vs static{}

I am writing some test cases using JUnit. I need to initialize some static variables which will be used for all the test cases in that class.
For this I can use either
Static initializer block or
Static method with #BeforeClass
What are the advantages of using one over another?
There are very different semantics for #BeforeClass or a static initializer.
A static initializer is invoked by the JVM and not by JUnit. If an exception is thrown within a static initializer, the test framework might not be able to catch and report the exception. Furthermore, the invocation time of the static initializer is not well-defined compared to the #BeforeClass method. It will be run only once per class loader on its first actual use which is for example the access of a static property, a static method or one of its constructors. Sometimes, it might be hard to figure out when this will be. (If you do not use inheritence: You might one day or some coworker will refactor your test case. If not today, the choice for a static initializer might introduce nasty bugs in the future.)
On the other hand, #BeforeClass is run before each class's tests are run. If a class would be subject to different tests, for example due to tests built on inheritance, the static initializer will only run for the first test using this class. This means that you made your test order dependent what is something you never want.
Note that the semantic difference between the two options is bigger than between using #Before or a constructor for a test. As a final argument, think about the documentary value of the annotations. It makes your intentions more readable.
The only exception for this rule would be immutable constants. Those should be initialized within their declaration in order to keep your code concise and in order to respect compile time constants. If your values are however mutable, you should not use static values at all. Again, mutable values that are altered in a test introduce an order dependency to your test which is to be avoided.
TL;DR: Use #BeforeClass!
Here's a couple of considerations that could be taken into account when deciding whether to use the static initialization block or #BeforeClass:
#BeforeClass is the antagonist of #AfterClass. So if you do initializations that require cleaning up later (like opening external resources) it would be better (from a semantic point of view) to use the annotated methods.
If you do complex initializations that might throw checked exceptions it's much more comfortable to use #BeforeClass, because you don't have to catch and wrap it into an unchecked exception.
If you want to use constant semantics (private static final String VARIABLE) with complex initialization, you will have no choice but to use the static initialization block or a static method.
There is a related post on SO: unit testing - What's the difference between using #BeforeClass and using instance or static variable in JUnit 4 Java?
If it's both static and final then you only have one choice: static initializer.
The compiler will prevent you from writing to a final field from inside a method, static or not.
EDIT: OK, you've removed the word 'final' from your question. In that case, it makes little difference. The static initializer will run once; so will the #BeforeClass method. Just pick whichever one you think is more readable.
It's not exactly the same behavior. #BeforeClass runs everytime the tests are run, a static initializer only once when the class is loaded. If your testrunner uses the same classloader, then in the case of #BeforeClass, you would re-run the initialization of the static variable. It depends on what you want to achieve here.

Categories