JUnit #Before vs #Rule - java

I understand that,
#Before and #BeforeClass run before each test, or the entire test class, respectively
#Rule and #ClassRule wraps each test, or the entire test class, respectively.
Let's say I need to initialize some data before each test method,
How do I decide between using #Before and #Rule? Under what conditions is one preferred over another? The same question also goes for #BeforeClass vs.#ClassRule.

In order to use #Rule, you require a class that implements TestRule(preferred) or MethodRule, as can be read here.
Whereas #Before and #After require a new method to be written in every test case, #Rule does not because it is only an instantiation of already existing code.
So, if you would use #Before and #After for setUp() and tearDown() that you'll be using in many test cases, it is actually a better idea to use #Rule because of code reuse. If you have a test case that requires a unique #Before and/or #After, then these annotations are preferable.
For a bit more elaborate answer with a couple examples, take a look here. Ajit explains it very well.

Indeed, as #Quwin suggested, accoridng to JUnit 4.12 API doc,
TestRule can do everything that could be done previously with
methods annotated with #Before, #After, #BeforeClass, or
#AfterClass, but TestRules are (1) more powerful, and (2) more easily shared
between projects and classes.
Ways that TestRules are more powerful:
There are known implementing classes of the TestRule, which are some usefuls rules you can use out-of-the-box,
For examples of how this can be useful, see these provided TestRules, or write your own:
ErrorCollector: collect multiple errors in one test method
ExpectedException: make flexible assertions about thrown exceptions
ExternalResource: start and stop a server, for example
TemporaryFolder: create fresh files, and delete after test
TestName: remember the test name for use during the method
TestWatcher: add logic at events during method execution
Timeout: cause test to fail after a set time
Verifier: fail test if object state ends up incorrect
Another benefit of rules, is that multiple rules can be used in a single test case. You may want to use RuleChain to specify the order in which the rules should be run.

Related

Java and JUnit, find missing #Test decorators

Let's say we have a project full of unit tests (thousands) and they all should look like this
#Test
public void testExceptionInBla() {
// some test
}
But in one case someone forgot to put an #Test decorator on top of the test.
What would be an easy way to spot those tests, without looking through all the code manually?
I want to find code like this, it's a test without #Test:
public void testExceptionInBla() {
// some test
}
I were you I would look at some Sonnar rule here I found something that may can match requirement:
https://rules.sonarsource.com/java/RSPEC-2187
But in one case someone forgot to put an #Test decorator on top of the
test.
And
I want to find code like this, it's a test without #Test:
public void testExceptionInBla() { // some test }
Annotating the method with #Test or specifying a test prefix in the method name is about the same thing in terms of consequences if the developer forgets to do that.
If the #Test is the way today, that is not chance.
The #Test annotation brings two real advantages on the test prefix :
1) it is checked at compile test. For example #Tast will provoke a compilation error while tastWhen...() will not.
2) #Test makes the test method name more straight readable : it allows to focus on the scenario with a functional language.
should_throw_exception_if_blabla() sounds more meaningful than test_should_throw_exception_if_blabla().
About your issue : how to ensure that tests are effectively executed, I would take things in another way. Generally you want to ensure that unit tests execution covers a minimum level of the application source code (while you can go down at package or class level if makes sense).
And that is the coverage tools goal (Jacoco for example) to do that job.
You can even add rules to make the build fail if the level of coverage of classes belonging to some package are not covered at least at a specified minimum level (look at that post).
Small Adding :
If you really ensure that methods of test are correctly annotated, you have a way :
1) you have to choose a convention for test methods : for example all instance and not private methods in a test class are test methods.
2) Create a Sonar rule that retrieves all non private instance methods of test classes and ensure that all these methods are annotated with #Test.
3) Add that rule to your Sonar rules.

JUnit test cleanup for single method

I have a JUnit test class with a number of different test cases. One of these test cases has bit different test setup and cleanup than the other ones. What is the best way to do test cleanup in such scenario? Extract test case into separate class and use standard #Before and #After annotations?
Make a subclass with only that test, write custom #Before and #After methods calling super ones if needed.

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

PowerMock, how to make a static method return value more than once?

This may be a simple question, but I could not find an answer with reasonable search.
I am trying to make a static method return a value more than once in multiple tests. I fail to achieve this with the mocked static method with PowerMock. To put this simply I have a JUnit test #BeforeClass like this
#RunWith(PowerMockRunner.class)
#PrepareForTest(StaticStuff.class)
public class MyTest extends TestCase {
#BeforeClass
public static void init() {
// Mock some stuff
PowerMockito.mockStatic(StaticStuff.class);
Mockito.when(StaticStuff.get()).thenReturn("something");
}
}
Now, this works for the first test accessing the static method, but the rest will receive 'null' (update: or any other value that the "real" method would return). I can fix the problem simply changing the #BeforeClass to #Before, thus making the static mock be recreated for every test. But afaik, this is not the correct way to do this. For this particular case this will do, but I believe there should be a way to provide information that the method may be called "any times".
Actually I understood from the documentation that the same value should be returned "infinite times by default" (but it doesn't. From Mockito documentation: 'Once stubbed, mocked method will always return stubbed value regardless of how many times it is called.'). Also I would expect that stating the amount of calls should be something this simple (but it isn't):
Mockito.when(StaticStuff.get()).thenReturn("something").times(10);
Maybe I am just missing something?
The tests should be independent from each other. If you use JUnit, the order of the tests is not determined at all (see https://github.com/junit-team/junit/wiki/Test-execution-order). I think creating mocks in #BeforeClass is actually a bad practice, since it can cause that the tests are depending on each other. So I would simply recommend to use #Before method to initialize all mocks, and use #BeforeClass only, if you prepare something really common for the tests (like a connection pool or something like that).

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.

Categories