Newsletter:

(FAQ) JUnit Interview Questions Page 2

FAQ : JUnit Interview Questions Page 2

Page 1 | Page 2 | Page 3

How do I test a method that doesn't return anything?
Often if a method doesn't return a value, it will have some side effect. Actually, if it doesn't return a value AND doesn't have a side effect, it isn't doing anything.

There may be a way to verify that the side effect actually occurred as expected. For example, consider the add() method in the Collection classes. There are ways of verifying that the side effect happened (i.e. the object was added). You can check the size and assert that it is what is expected:

@Test
public void testCollectionAdd() {
Collection collection = new ArrayList();
assertEquals(0, collection.size());
collection.add("itemA");
assertEquals(1, collection.size());
collection.add("itemB");
assertEquals(2, collection.size());
}
Another approach is to make use of MockObjects.

A related issue is to design for testing. For example, if you have a method that is meant to output to a file, don't pass in a filename, or even a FileWriter. Instead, pass in a Writer. That way you can pass in a StringWriter to capture the output for testing purposes. Then you can add a method (e.g. writeToFileNamed(String filename)) to encapsulate the FileWriter creation.

Under what conditions should I test get() and set() methods?
Unit tests are intended to alleviate fear that something might break. If you think a get() or set() method could reasonably break, or has in fact contributed to a defect, then by all means write a test.

In short, test until you're confident. What you choose to test is subjective, based on your experiences and confidence level.

Under what conditions should I test get() and set() methods?
Unit tests are intended to alleviate fear that something might break. If you think a get() or set() method could reasonably break, or has in fact contributed to a defect, then by all means write a test.

Under what conditions should I not test get() and set() methods?
Most of the time, get/set methods just can't break, and if they can't break, then why test them? While it is usually better to test more, there is a definite curve of diminishing returns on test effort versus "code coverage". Remember the maxim: "Test until fear turns to boredom."

Assume that the getX() method only does "return x;" and that the setX() method only does "this.x = x;". If you write this test:

@Test
public void testGetSetX() {
setX(23);
assertEquals(23, getX());
}
then you are testing the equivalent of the following:

@Test
public void testGetSetX() {
x = 23;
assertEquals(23, x);
}
or, if you prefer,

@Test
public void testGetSetX() {
assertEquals(23, 23);
}
At this point, you are testing the Java compiler, or possibly the interpreter, and not your component or application. There is generally no need for you to do Java's testing for them.

If you are concerned about whether a property has already been set at the point you wish to call getX(), then you want to test the constructor, and not the getX() method. This kind of test is especially useful if you have multiple constructors:

@Test
public void testCreate() {
assertEquals(23, new MyClass(23).getX());
}

How do I write a test that passes when an expected exception is thrown?
Add the optional expected attribute to the @Test annotation. The following is an example test that passes when the expected IndexOutOfBoundsException is raised:

@Test(expected=IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}

How do I write a test that fails when an unexpected exception is thrown?
Declare the exception in the throws clause of the test method and don't catch the exception within the test method. Uncaught exceptions will cause the test to fail with an error.

The following is an example test that fails when the IndexOutOfBoundsException is raised:

@Test
public void testIndexOutOfBoundsExceptionNotRaised()
throws IndexOutOfBoundsException {
   
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}

How do I test protected methods?
Place your tests in the same package as the classes under test.

Why does JUnit only report the first failure in a single test?
Reporting multiple failures in a single test is generally a sign that the test does too much, compared to what a unit test ought to do. Usually this means either that the test is really a functional/acceptance/customer test or, if it is a unit test, then it is too big a unit test.

JUnit is designed to work best with a number of small tests. It executes each test within a separate instance of the test class. It reports failure on each test. Shared setup code is most natural when sharing between tests. This is a design decision that permeates JUnit, and when you decide to report multiple failures per test, you begin to fight against JUnit. This is not recommended.

Long tests are a design smell and indicate the likelihood of a design problem. Kent Beck is fond of saying in this case that "there is an opportunity to learn something about your design." We would like to see a pattern language develop around these problems, but it has not yet been written down.

Finally, note that a single test with multiple assertions is isomorphic to a test case with multiple tests:

One test method, three assertions:


public class MyTestCase {
@Test
public void testSomething() {
// Set up for the test, manipulating local variables
assertTrue(condition1);
assertTrue(condition2);
assertTrue(condition3);
}
}
Three test methods, one assertion each:


public class MyTestCase {
// Local variables become instance variables

@Before
public void setUp() {
// Set up for the test, manipulating instance variables
}
   
@Test
public void testCondition1() {
assertTrue(condition1);
}

@Test
public void testCondition2() {
assertTrue(condition2);
}

@Test
public void testCondition3() {
assertTrue(condition3);
}
}
The resulting tests use JUnit's natural execution and reporting mechanism and, failure in one test does not affect the execution of the other tests. You generally want exactly one test to fail for any given bug, if you can manage it. 

Page 1 | Page 2 | Page 3