Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

MockLib: Simulate APIs for Testing : Page 4

Using MockLib, a tool that simulates entire APIs, you can unit test contracts or well-defined APIs and refactor whole components with very few changes to your tests.


advertisement
Passing the Timers
Now you'll see how to create unit tests when timers are involved. The example system is a CalendarService where events will be scheduled. When they go off, they will fire to listeners that are listening for the start of events. This example builds on the first. Notice Figure 3 is very much like the first example except for the addition of a MockTimer. It also shows more details of the system you are testing in that it contains a TimerTask with code that you will test.

Click to enlarge

Figure 3. Unit Testing with Timer Simulation

Before you start working on the timer system and tests, you need an interface for the timer used in Java. Start by creating TimerInterface.java with the following methods:



17 public interface TimerInterface { 18 19 public void cancelTask(TimerTask task); 24 public void schedule(TimerTask task, long delay); 28 29 }

An upcoming section will explain the purpose of adding the cancelTask method, which is not a method on Java's timer. For now, move on to the system you plan on testing. The API of that system is as follows:

05 public interface CalendarService { 06 07 public abstract void addEvent(String title, long delay); 08 09 public abstract void cancelEvent(String title); 10 11 public abstract void addScheduleListener(ScheduleListener l); 12 13 public abstract void removeScheduleListener(ScheduleListener l); 14 }

This system is for scheduling events in the future. When an event goes off, it will then notify the ScheduleListener listener. Now, the last part of the API is the ScheduleListener itself used to notify a client that the event has started:

16 public interface ScheduleListener extends EventListener { 17 18 /** 19 * @param title 20 */ 21 void eventStarted(String title); 22 23 }

Looking at this API, you basically would like to add an event that will go off in 24 hours, simulating a real client. The only problem is you don't want to wait 24 hours for the test to run. To resolve this, start your test by creating your mock timer and your service just like in the previous examples:

044 //Create a mockTimer which acts as a cache for TimerTasks..... 045 mockTimer = MockObjectFactory.createMock(TimerInterface.class); 046 calendar = new CalendarServiceImpl((TimerInterface) mockTimer);

Now, just like the first example, your test needs to simulate adding a ScheduleListener. This is of course a mock ScheduleListener. Here is the initial code:

047 048 //Create and add a mockListener which you use to verify receiving of the 049 //proper events.... 050 mockListener = MockObjectFactory.createMock(ScheduleListener.class); 051 calendar.addScheduleListener((ScheduleListener)mockListener);

Now that everything is set up properly, you are ready to actually test the system. Start by adding an event to your CalendarService:

069 String title = "some event"; 070 long delay = 50000; 071 calendar.addEvent(title, delay);

Which method do you expect to be called on your mock timer now? I will give you a hint: There are only two methods and one is only for canceling tasks. That's right, a TimerTask will be scheduled on the Mock Timer:

073 //When an event is added, you expect schedule on the timer to be called... 074 CalledMethod method = mockTimer.expect("schedule"); 075 //param[0] is the mock object's cached timer task.... 076 TimerTask task = (TimerTask)method.getParameter(0); 077 assertEquals("Should have set the timer for "+delay+" ms", new Long(delay), method.getParameter(1));

Notice that right after you expect schedule to be called you grab the parameters that were passed to that schedule method—the TimerTask and the delay. You verify that CalendarService scheduled the event to happen 50,000 milliseconds in the future, so you know that is correct. However, there is no reason to wait 50,000 milliseconds to run the TimerTask; now that you retrieved the TimerTask, you might as well run it right away. When you run the TimerTask, you then immediately expect the Mock ScheduleListener to receive an event as well. The following code demonstrates this:

079 //We already verified it was scheduled in the future, so there is 080 //no need to wait till run the task then 081 //run the task now instead of waiting 50000ms 082 task.run(); 083 084 //expect that the listener's eventStarted method is called with the 085 //property event title 086 method = mockListener.expect("eventStarted"); 087 assertEquals("title should be the same", title, method.getParameter(0));

As usual, I leave it up to you to write the implementation of CalendarService. The first test is provided above. Also, as usual, you can find one solution here.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap