Junit: How to make every #Test methods isolated completely? - java

Example code:
public class Count {
static int count;
public static int add() {
return ++count;
}
}
I want test1 and test2 run totally separately so that they both pass. How can I finish that? My IDE is Intellij IDEA.
public class CountTest {
#Test
public void test1() throws Exception {
Count.add();
assertEquals(1, Count.count);//pass.Now count=1
}
#Test
public void test2() throws Exception {
Count.add();
assertEquals(1, Count.count);//error, now the count=2
}
}
Assume the test1 runs before test2.
This is just a simplified code. In fact the code is more complex so I can't just make count=0 in #after method.

There is no automated way of resetting all the static variables in a class. This is one reason why you should refactor your code to stop using statics.
Your options are:
Refactor your code
Use the #Before annotation. This can be a problem if you've got lots of variables. Whilst its boring code to write, if you forget to reset one of the variables, one of your tests will fail so at least you'll get chance to fix it.
Use reflection to dynamically find all the member of your class and reset them.
Reload the class via the class loader.
Refactor you class. (I know I've mentioned it before but its so important I thought it was worth mentioning again)
3 and 4 are a lot of work for not much gain. Any solution apart from refactoring will still give you problems if you start trying to run your tests in parallel.

Use the #Before annotation to re-initialize your variable before each test :
#Before
public void resetCount(){
Count.count = 0;
}

Related

How to reuse method and test in JUnit?

I've tried to avoid duplicate code in JUnit test, but I'm kind of stuck.
This is my first test, for the second one it has exactly the same methods but different service (different input). instead of the TestCaseResourceTest1 I have TestCaseResourceTest2. Now what could be the proper way to test both? I want to have a separate file for test number 2, how should I avoid the duplicate code? (ex. use the beforeFileTest() method)
public class TestCaseResourceTest1 {
#Mock
private TestService testService;
#Mock
private AreaService areaService;
private TestCaseService1 testCaseService1; // is changed in test2
#Before
public void before() throws Exception{
testCaseService1 = mock(TestCaseService1.class); // is changed in test2
MockitoAnnotations.initMocks(this);
beforeFileTest();
}
private void beforeFileTest() throws Exception{
doReturn(true).when(areaService).chechExists(any(String.class), eq(false));
}
#Test
public void verifyFileExists() throws Exception{
verifyOtherArea(testCaseService1); // is changed in test2
doReturn(false).when(areaService).chechExists(any(String.class), eq(false));
}
}
just lines with comment is changed in test2 are differences.
Tnx
Given this excerpt from your question:
… instead of the TestCaseResourceTest1 I have TestCaseResourceTest2 … I want to have a separate file for test number 2
… the standard ways of sharing code between test cases are:
Create a Test Suite and include the shared code in the test suite (typically in #BeforeClass and #AfterClass methods). This allows you to (1) run setup code once (per suite invocation); (2) encapsulate shared setup/teardown code and (3) easily add more tests cases later. For example:
#RunWith(Suite.class)
#Suite.SuiteClasses({
TestCaseResourceTest1.class,
TestCaseResourceTest2.class
)}
public class TestSuiteClass {
#BeforeClass
public void setup() {
beforeFileTest();
}
private void beforeFileTest() throws Exception {
// ...
}
}
Create an abstract class which parents TestCaseResourceTest1 and TestCaseResourceTest2 and let those test cases call the shared code in the parent (typically via super() calls). With this approach you can declare default shared code in the parent while still allowing sub classes to (1) have their own behaviour and (2) selectively override the parent/default behaviour
Create a custom JUnit runner, define the shared behaviour in this runner and then annotate the relevant test cases with #RunWith(YourCustomRunner.class). More details on this approach here
Just to reiterate what some of the other posters have said; this is not a common first step so you may prefer to start simple and only move to suites or abstract classes or custom runners if your usage provides a compelling reason to do so.
I had the such situation and it was a sign about wrong implementation design. We are talking about pure unit tests where we test exactly what is implemented in the production classes. If we need duplicated tests it means we probably have duplication in implementation.
How did I resolve it in my project?
Extracted common logic into parent service class and implemented unit tests for it.
For child services I implemented tests only for particular implemented code there. No more.
Implemented an integration tests on real environment were both services were involved and tested completely.
Assuming you want to have the exact same test run for 2 different classes (and not mocking it as in your example code), you can create an abstract test class, that has abstract method that returns an instance of the class to be tested.
Something in the vein of:
public abstract class TestCaseResourceTest {
protected abstract TestCaseService1 getServiceToTest();
#Before
public void before() throws Exception {
testCaseService1 = getServiceToTest();
MockitoAnnotations.initMocks(this);
beforeFileTest();
}
#Test
public void test() {
// do your test here
}
}
public class ConcreteTest extends TestCaseResourceTest {
protected TestCaseService1 getServiceToTest() {
return new TestCaseService();
}
}
public class ConcreteTest2 extends TestCaseResourceTest {
protected TestCaseService1 getServiceToTest() {
return new DifferentService();
}
}
Have you considered using JUnit 5 with its http://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests ?
It allows you to re-use your tests with different input. This is an example from the documentation which illustrates what you can do now with JUnit 5:
#ParameterizedTest
#ValueSource(strings = { "Hello", "World" })
void testWithStringParameter(String argument) {
assertNotNull(argument);
}
But you can also create your methods which return the input data:
#ParameterizedTest
#MethodSource("stringProvider")
void testWithSimpleMethodSource(String argument) {
assertNotNull(argument);
}
static Stream<String> stringProvider() {
return Stream.of("foo", "bar");
}
Here I am using just strings, but you can really use any objects.
If you are using Maven, you can add these dependencies to start using JUnit 5:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.0.0-RC2</version>
<scope>test</scope>
</dependency>
The only annoying thing about JUnit 5 is that it is not released yet.
When going from one test to two tests, you don't know what will be duplicate code, so I find it useful to put everything into one test method. In this case, start by putting the contents of the #Before and beforeFileTest methods inline in the test.
Then you can see that it is just te service that needs changing, so you can extract everything except that into a helper method that is called from two tests.
Also, after you have two tests that are calling the same helper method and are happy with that test coverage, you could look into writing parameterized tests. For example with JunitParams: https://github.com/Pragmatists/junitparams/wiki/Quickstart

Change the value for each test method before #Before annotation is called in JUnit

I am writing a test for a class which has a setup
class A
{
private String name;
public String getName()
{
return "Hello "+ name;
}
public void setName(String name)
{
this.name = name;
}
My test class
TestA
A a = new A();
{
#Before
void setup()
{
a.setName("Jack");
}
#Test
public void testTom()
{
assert(a.getString(), "Hello Tom");
}
#Test
public void testJack()
{
assert(a.getString(), "Hello Jack");
}
How to change the value of name between the methods since #Before calls for every test method?
ie) if execute testJack then the output should be Hello Jack.
I tried with #Parameters but before that setup is getting called so i couln't acheive this functionality.
First, the code:
#Before
void setup()
{
A a = new A();
a.setName("Jack");
}
Doesn't do anything which the Tests can see. You're creating a local variable a which goes out of scope almost immediately.
#Before is designed to set and reset a state or context before each Test is run. It doesn't vary unless something it relies on changes between invocations.
You could create a Stack as an instance variable and pre-populate it in a #BeforeClass method, and have #Before pop a value to be used every time it's called. This is unadvisable as it assumes that the Tests will be run in some particular order. It's much cleaner and clearer to just declare different values inside each Test.
There is simply no point in doing that; as your real problem is rooted in your statement "Just assume the scenario of 30 lines of code in setup".
If you need 30 lines of setup code, then your code under test is not following the "single responsibility principle" and doing way too many different things.
Of course, you can turn to "data driven" testing to somehow get there (see here for example); but that would be fixing the Y side of an XY problem.
I know, it sounds harsh: but you better step back; and learn about doing reasonable OO design (for example based on SOLID). Then you rework your code to not need 30 lines of setup code.
You see, if your code is so hard to test; I guarantee you: it is also hard to understand, and will be close to impossible to maintain/enhance over time. And beyond that: it will be even hard to get your code to be "correct" in the first place.
Long story short: have a look in these videos and improve your design skills.

how to initialize JUnit test classes before running in parallel

I am trying to execute JUnit tests in parallel using the ParallelComputer experimental feature, however I do not know how to pre-initialize each of the test classes before kicking off the tests.
The classic example of how these are supposed to be used is as follows (as shown in the following GitHub link). Per the example, how do I initialize the ParallelTest1 and ParallelTest2 classes with shared data before starting the parallel thread testing. I was able to do this via constructors in each of the classes, however I need to make sure that both classes are fully initialized before the run starts. This problem is probably not specific to the Parallel nature of how I wish to perform the testing but more likely how to use some special keywords to order prevent initialized objects from starting until required. Ideally the example ParallelComputerTest could have this shared data initialized in its constructor, however in that case, how could the nested static parallel test classes get access to this instance data?
public class ParallelComputerTest {
#Test
public void test() {
Class[] cls={ParallelTest1.class,ParallelTest2.class };
//Parallel among classes
JUnitCore.runClasses(ParallelComputer.classes(), cls);
//Parallel among methods in a class
JUnitCore.runClasses(ParallelComputer.methods(), cls);
//Parallel all methods in all classes
JUnitCore.runClasses(new ParallelComputer(true, true), cls);
}
public static class ParallelTest1{
#Test public void a(){}
#Test public void b(){}
}
public static class ParallelTest2{
#Test public void a(){}
#Test public void b(){}
}
}
Use #Before for set ups and #After for clean ups.
For example to test console output I set up streams before and clean result after test like this:
#Before
public void setUpStreams() {
System.setOut(new PrintStream(outContent));
System.setErr(new PrintStream(errContent));
}
#After
public void cleanUpStreams() {
System.setOut(null);
System.setErr(null);
}
NOTE: this can cause problems with TestSuite, dunno if also with ParallelTest. If you experience some troubles AND you use JUnit 4.7 or higher you might like to check this link to rules feature

Junit - method at the end of each test

I got a method that I call at the end of every test to reset the streams positions.
Test{
[....]
reset();
}
Is there any elegant way to avoid such a repetition?
Try #After annotaton, that goes with JUnit.
Example from source:
public class Example {
File output;
#Before public void createOutputFile() {
output= new File(...);
}
#Test public void something() {
...
}
#After public void deleteOutputFile() {
output.delete();
}
}
the other answers suggest the #After annotation on a public method (preferably with name teardown) which is technically right and a good answer to your question.
But essential properties of unittests is that they need to be fast and independent of each other.
Therefore the better approach is to use a fresh mock of the stream with every test. This is best done by using a mocking framework like Mockito, JMock or alike.
Yes, create new method with #After annotation.
You should use the #After annotation - indicates something needs to be done at the end of each method run.
Use #After annotation.
#Test
public void testSomething() {
// test goes here
}
#After
public void doSomethingAfterTest() {
// reset
}
As others have pointed out, there are the #s: Before and After. Class instance methods with these annotations will run before/after every test case.
There is also BeforeClass and AfterClass, which I didn't see anyone point out yet. These #s may be put onto static methods of your class, and those methods will execute before and after all of the tests in your class have completed. It is handy in certain situations.

JUnit: No runnable methods

I am newbie in JUnit. I am fixing JUnit in SonarQube report and also increasing Junit code coverage. I came across of a class where there is no #Test annotation. The Exception thrown is as below:
No runnable methods java.lang.Exception: No runnable methods at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
Test class below:
public class TestLimitPrice {
#BeforeClass
public static void setUpBeforeClass() {
JndiDataManager.init();
}
private LimitPriceBean limitPrice;
private LimitPriceValidator validator;
#Before
public void setUp() {
limitPrice = new LimitPriceBean();
validator = new LimitPriceValidator(limitPrice);
}}
My Question's are :
In Sonar Report is it necessary for every JUnit to have atleast one #Test to pass ?
Will empty #Test is good approach for increasing code coverage ?
If in case any test case is not executing, then assertEquals(true,true) is good practice or should be avoided ?
Update
Sonar Version 4.4.1
JUnit Version 4.12
Java 1.6-45
My Question's are :
In Sonar Report is it necessary for every JUnit to have at least one
#Test to pass ?
I don't understand the question.
Will empty #Test is good approach for increasing code
coverage ?
No, for two reasons.
First, if the #Test method is truly empty, then there's no possibility to increase coverage. So let's assume that you have a #Test method that does execute some of your program code but that contains no assertions.
In this scenario, you've increased your test coverage by executing program code in a #Test but totally subverted the purpose of tests by not making any statements (assertions) about the expected outcome / outputs of that code. Let's say I've got
public int addTwoAndTwo() {
return 2+2;
}
And a corresponding test
#Test public void testAddTwoAndTwo() {
MyClass mc = new MyClass();
my.addTwoAndTwo(); // this method now "covered"
}
Now that addTwoAndTwo is "covered" I'm supposed to be able to maintain it with confidence that as long as the unit tests continue to pass, I haven't broken anything.
So let's do that. My new version is this:
public int addTwoAndTwo() {
return 42;
}
After that change, my unit tests still succeed, so everything must be okay, right? Uhm... no. And that's why you need assertions:
#Test public void testAddTwoAndTwo() {
MyClass mc = new MyClass();
assertThat(mc.addTwoAndTwo()).isEqualTo(4); // this method now truly covered
}
If in case any test case is not executing, then
assertEquals(true,true) is good practice or should be avoided ?
The answer to this question should by now be obvious, but to be explicit, DO NOT DO THIS.

Categories