Contents
You can control the passage of time when running StreamBase JUnit tests of EventFlow applications. This feature allows you to run unit tests of modules that react to time, such as those containing timeouts or those that use metronomes. Using the TimeService to set a custom start time is analogous to temporarily setting the BIOS system time of the machine hosting StreamBase Server, when using exclusively StreamBase APIs and facilities to obtain time or duration.
For example, you can run a unit test, enqueue events that should all be received by the application within one second, and then tell the Server that the one-second time period has elapsed. This allows you to align the EventFlow logic more closely with a real-world input stream.
See Creating and Running StreamBase JUnit Tests for an introduction to configuring and running StreamBase JUnit tests.
To manage the reference starting point time of a StreamBase module, you must configure the sbd.sbconf
file of the containing project to use the <time-service-configurations>
element and one or two of its sub-elements.
To be able to advance the current time of a running StreamBase Server, the project's sbd.sbconf
must contain the following:
<time-service-configurations> <type>CONTROLLABLE</type> </time-service-configurations>
To restore the default behavior, change the CONTROLLABLE keyword to WALLCLOCK, or comment out the entire element.
To specify a custom start timestamp for the module, use the <target-time>
child element in addition to <type>
. The <target-time>
element is ignored unless <type>
is set to CONTROLLABLE. For example:
<time-service-configurations> <type>CONTROLLABLE</type> <target-time>2015-10-06 12:00</target-time> </time-service-configurations>
When a StreamBase application is configured as described in the previous section, you can control the reference start time of the running application either at the command prompt or in expression language constructions.
-
Three expression language functions can be used to manage the running application's reference start time: advanceTimeBy(), advanceTimeTo(), and getTargetTime().
-
Two jsbadmin subcommands, getTargetTime and fastForwardTime, can retrieve the current time and advance it by a specified number of milliseconds, as described on the jsbadmin reference page.
The overall steps to control time in your StreamBase unit tests are:
-
When configuring your StreamBase JUnit Java file, modify the BaseTestEnvironment's
NowImplementation
to use anIMPL_TIME_SERVICE
. -
Create a ControllableTimeService and set that as the server's time service.
-
In your test, use
timeService.advanceBy()
andadvanceTo()
to manage the clock.
The TimeServiceFactory
class methods create TimeService objects to manage time:
-
getWallClockTimeService()
— Returns a TimeService that uses wall clock time (that is, it uses your operating system's clock); this is the default. -
getControllableTimeService()
— Returns a ControllableTimeService instance initialized with the current system time. This is the usual starting point if you are trying to control time. -
getControllableTimeService(long initTargetTimeMsec)
— Returns a ControllableTimeService instance initialized with a specified time.
In the SBTestEnvironment
interface, the enum NowImplementation
indicates how now()
behaves. It takes these values:
-
IMPL_SYSTEM
— Uses calls toSystem.currentTimeMillis()
on the calling thread -
IMPL_THREAD
— Uses calls toSystem.currentTimeMillis()
on a dedicated thread -
IMPL_TIME_SERVICE
— Uses the currentTimeService
implementation to get the current time
To get the current implementation use getNowImpl()
. To set it to one of the above, use setNowImpl(NowImplementation)
.
In addition, the SBServerManager
class has two methods for time services:
-
getTimeService()
— Returns the current TimeService implementation used by StreamBase Server. -
setTimeService(TimeService timeservice)
— Set a TimeService for the StreamBase Server instance controlled by this Manager.The input TimeService value can be either a valid object or null. In the latter case it is assumed to be
WallClockTimeService
object.Caution
The
setTimeService
method is not thread safe. It can be called from any thread but it should not be called from more than one thread at the same time.
When you select an application to test and click
→ , the StreamBase Unit Test Class wizard opens. When you click , it generates code that begins like this:package com.sb.support.test; import com.streambase.sb.unittest.SBServerManager; import com.streambase.sb.unittest.ServerManagerFactory; public class baseMainTest { private static SBServerManager server; @BeforeClass public static void setupServer() throws Exception { // create a StreamBase server and load applications once for // all tests in this class server = ServerManagerFactory.getEmbeddedServer(); server.startServer(); server.loadApp("main.sbapp"); }
As the default time service is wall clock time, the wizard generates no code to control time service. To establish control
of time, modify the the @BeforeClass
block as follows:
@BeforeClass public static void setupServer() throws Exception { // create a StreamBase server and load applications once // for all tests in this class // Set NowImplementation to IMPL_TIME_SERVICE instead of the default BaseTestEnvironment.DEFAULT_ENVIRONMENT.setNowImpl(NowImplementation .IMPL_TIME_SERVICE); server = ServerManagerFactory.getEmbeddedServer(); // Create a ControllableTimeService to use as the server's time service timeService = TimeServiceFactory.getControllableTimeService(); server.setTimeService(timeService); server.startServer(); server.loadApp("main.sbapp"); }
Then, at the beginning of each test, you must initialize the time with this code:
timeService.advanceTo(System.currentTimeMillis());
When you advance the clock, specify the advance interval size and unit. In this example, the advance is 15 seconds:
timeService.advanceBy(15, TimeUnit.SECONDS);
See Java API Documentation in the StreamBase API Documentation for documentation on the classes involved, which are in the packages com.streambase.sb
and com.streambase.sb.unittest
.