Presents your JAVA E-NEWSLETTER for October 21, 2002 <-------------------------------------------> PERFORM UNIT TESTING WITH EASYMOCK Unit testing has grown in popularity partly due to the growth of eXtreme Programming. However, writing strong unit tests can be a boring chore. Mock objects can help reduce the tedium by faking the objects surrounding the target to be tested. The mock objects are then used to check that relevant calls were made to the target. EasyMock is a quick way to create mock objects while maintaining the power of unit testing. The typical use is to get EasyMock to: 1. Create a mock object for an interface. 2. Train that interface with the calls to expect and responses to make. 3. Test the target and verify the mock object. Here's an example of testing that a method, Mapper.map(Processor, Integer[]), maps calls to Processor.process on each integer in an array: public void testArrayProcessing() throws Exception { Integer[] numbers = new Integer[2] { new Integer(6), new Integer(7) }; // make a mock object MockControl control = EasyMock.controlFor (Processor.class); Processor mockProcessor = (Processor)control.getMock(); // train the object mockProcessor.process (numbers[0]); control.setReturnValue (new Integer(1)); mockProcessor.process (numbers[1]); control.setReturnValue (new Integer(1)); // turn it on control.activate (); // run the test Mapper.map(mockProcess, numbers); // verify the test control.verify(); } It is important to remember to call verify on the control, or else half of the training isn't tested. For example, if we have specified that the methods must return an integer of value '1', then calling verify ensures that that was the value returned. The order in which the methods are called in the training does not matter; however, we can specify that a method can only be called a certain number of times with: // assume Processor interface has a setName method, and that // our class, Mapper, will call this once per item. mockProcessor.setName("Test"); control.setVoidCallable(3); When we call verify, it will check how many times setName was called and report an error if it was called too often. EasyMock's main limitation is that it only works on interfaces, but as using interfaces is a good design habit, there's not much to complain about. EasyMock can save a lot of legwork and make unit tests a lot faster to write. EasyMock is available on the Web, along with a paper on mock objects and links to other mock object APIs. http://www.easymock.org/ ---------------------------------------- CORRECTION In the Oct. 28, 2002 TechMail ("Remove files recursively"), we told you how to safely delete a nonempty directory in a platform-independent way. Part of the sample code contained an error. The code originally read: static public void deleteDirectory(File dir) throws IOException { if( (dir == null) || !dir.isDirectory) { throw new IllegalArgumentException( "Argument "+dir+" is not a directory. " ); } It should have read: static public void deleteDirectory(File dir) throws IOException { if( (dir == null) || !dir.isDirectory()) { throw new IllegalArgumentException( "Argument "+dir+" is not a directory. " ); } We apologize for any inconvenience these errors may have caused. ----------------------------------------