I am looking for the following:
Consider using ExpectedException instead of @Test(expected.... This is because if for example you expect a NullPointerException and your test throws this exception in your setup (before calling the method under test) your test will pass. With ExpectedException you put the expect immediately before the call to the method under test so there is no chance of this. Also, ExpectedException allows you to test the exception message which is helpful if you have two different IllegalArgumentExceptions that might be thrown and you need to check for the correct one.
Consider isolating your method under test from the setup and verify, this will ease in test review and maintenance. This is especially true when methods on the class under test are invoked as part of setup which can confuse which is the method under test. I use the following format:
public void test() {
//setup
...
// test (usually only one line of code in this block)
...
//verify
...
}
Books to look at: Clean Code, JUnit In Action, Test Driven Development By Example
Clean Code has an excellent section on testing
Most example I have seen (including what Eclipse autogenerates) have the method under test in the title of the test. This facilitates review and maintenance. For example: testOfComponents_nullCase. Your example is the first I have seen that uses the Enclosed to group methods by method under test, which is really nice. However, it adds some overhead as @Before and @After do not get shared between enclosed test classes.
I have not started using it, but Guava has a test library: guava-testlib. I have not had a chance to play with it but it seems to have some cool stuff. For example: NullPointerTest is quote:
- A test utility that verifies that your methods throw {@link * NullPointerException} or {@link UnsupportedOperationException} whenever any * of their parameters are null. To use it, you must first provide valid default * values for the parameter types used by the class.
Review: I realize the test above was just an example but since a constructive review might be helpful, here you go.
In testing getComponents, test the empty list case as well. Also, use IsIterableContainingInOrder.
In testing of ofComponents, it seems that it would make sense to call getComponents or toString to validate that it properly handled the various non-error cases. There should be a test where no argument is passed to ofComponents. I see that this is done with ofComponents( new String[]{}) but why not just do ofComponents()? Need a test where null is one of the values passed: ofComponents("blah", null, "blah2") since this will throw an NPE.
In testing ROOT, as has been pointed out before, I suggest calling ROOT.getComponents once and doing all three verifications on it. Also, ItIterableContainingInOrder does all three of not empty, size and contains. The is in the tests is extraineous (although it is linguistic) and I feel is not worth having (IMHO).
In testing toString, I feel it is very helpful to isolate the method under test. I would have written toStringIsSlashSeparatedPathOfComponents as follows. Notice that I do not use the constant from the class under test. This is because IMHO, ANY functional change to the class under test should cause the test to fail.
@Test
public void toStringIsSlashSeparatedPathOfComponents() {
//setup
String[] components = { "Test1", "Test2", "Test3" };
String expectedPath = "/" + Joiner.on("/").join(components);
MyPath path = MyPath.ofComponents(components)
// test
String value = path.toStrign();
// verify
assertThat(value, equalTo(expectedPath));
}
Enclosed will not run any unit test that is not in an inner class. Therefore testPathCreationFromComponents would not be run.
Finally, use Test Driven Development. This will ensure that your tests are passing for the right reason and will fail as expected.