public interface TestWorkflowEnvironment
Testing the workflow code is hard as it might be potentially very long running. The included in-memory implementation of the Cadence service supports an automatic time skipping. Anytime a workflow under the test as well as the unit test code are waiting on a timer (or sleep) the internal service time is automatically advanced to the nearest time that unblocks one of the waiting threads. This way a workflow that runs in production for months is unit tested in milliseconds. Here is an example of a test that executes in a few milliseconds instead of over two hours that are needed for the workflow to complete:
public class SignaledWorkflowImpl implements SignaledWorkflow {
private String signalInput;
@Override
public String workflow1(String input) {
Workflow.sleep(Duration.ofHours(1));
Workflow.await(() -> signalInput != null);
Workflow.sleep(Duration.ofHours(1));
return signalInput + "-" + input;
}
@Override
public void processSignal(String input) {
signalInput = input;
}
}
@Test
public void testSignal() throws ExecutionException, InterruptedException {
TestWorkflowEnvironment testEnvironment = TestWorkflowEnvironment.newInstance();
// Creates a worker that polls tasks from the service owned by the testEnvironment.
Worker worker = testEnvironment.newWorker(TASK_LIST);
worker.registerWorkflowImplementationTypes(SignaledWorkflowImpl.class);
worker.start();
// Creates a WorkflowClient that interacts with the server owned by the testEnvironment.
WorkflowClient client = testEnvironment.newWorkflowClient();
SignaledWorkflow workflow = client.newWorkflowStub(SignaledWorkflow.class);
// Starts a workflow execution
CompletableFuture result = WorkflowClient.execute(workflow::workflow1, "input1");
// The sleep forwards the service clock for 65 minutes without blocking.
// This ensures that the signal is sent after the one hour sleep in the workflow code.
testEnvironment.sleep(Duration.ofMinutes(65));
workflow.processSignal("signalInput");
// Blocks until workflow is complete. Workflow sleep forwards clock for one hour and
// this call returns almost immediately.
assertEquals("signalInput-input1", result.get());
// Closes workers and releases in-memory service.
testEnvironment.close();
}
Modifier and Type | Method and Description |
---|---|
void |
awaitTermination(long timeout,
java.util.concurrent.TimeUnit unit)
Blocks until all tasks have completed execution after a shutdown request, or the timeout
occurs, or the current thread is interrupted, whichever happens first.
|
void |
close()
Calls
shutdownNow() and awaitTermination(long, TimeUnit) . |
long |
currentTimeMillis()
Returns the current in-memory test Cadence service time in milliseconds.
|
java.lang.String |
getDiagnostics()
Returns the diagnostic data about the internal service state.
|
java.lang.String |
getDomain() |
Worker.Factory |
getWorkerFactory() |
IWorkflowService |
getWorkflowService()
Returns the in-memory test Cadence service that is owned by this.
|
boolean |
isShutdown()
Was
shutdownNow() or shutdown() called? |
boolean |
isStarted()
Was
start() called? |
boolean |
isTerminated()
Are all tasks done after
shutdownNow() or shutdown() ? |
static TestWorkflowEnvironment |
newInstance() |
static TestWorkflowEnvironment |
newInstance(TestEnvironmentOptions options) |
Worker |
newWorker(java.lang.String taskList)
Creates a new Worker instance that is connected to the in-memory test Cadence service.
|
Worker |
newWorker(java.lang.String taskList,
java.util.function.Function<WorkerOptions.Builder,WorkerOptions.Builder> overrideOptions)
Creates a new Worker instance that is connected to the in-memory test Cadence service.
|
WorkflowClient |
newWorkflowClient()
Creates a WorkflowClient that is connected to the in-memory test Cadence service.
|
WorkflowClient |
newWorkflowClient(WorkflowClientOptions clientOptions)
Creates a WorkflowClient that is connected to the in-memory test Cadence service.
|
void |
registerDelayedCallback(java.time.Duration delay,
java.lang.Runnable r)
Registers a callback to run after the specified delay according to the test Cadence service
internal clock.
|
void |
shutdown()
Initiates an orderly shutdown in which polls are stopped and already received decision and
activity tasks are executed.
|
void |
shutdownNow()
Initiates an orderly shutdown in which polls are stopped and already received decision and
activity tasks are attempted to be stopped.
|
void |
sleep(java.time.Duration duration)
Wait until internal test Cadence service time passes the specified duration.
|
void |
start()
Start all workers created by this factory.
|
static TestWorkflowEnvironment newInstance()
static TestWorkflowEnvironment newInstance(TestEnvironmentOptions options)
Worker newWorker(java.lang.String taskList)
taskList
- task list to poll.Worker newWorker(java.lang.String taskList, java.util.function.Function<WorkerOptions.Builder,WorkerOptions.Builder> overrideOptions)
taskList
- task list to poll.overrideOptions
- is used to override the default worker options.WorkflowClient newWorkflowClient()
WorkflowClient newWorkflowClient(WorkflowClientOptions clientOptions)
clientOptions
- options used to configure the client.long currentTimeMillis()
System.currentTimeMillis()
due to time skipping.void sleep(java.time.Duration duration)
void registerDelayedCallback(java.time.Duration delay, java.lang.Runnable r)
IWorkflowService getWorkflowService()
java.lang.String getDomain()
java.lang.String getDiagnostics()
@Rule
public TestWatcher watchman =
new TestWatcher() {
@Override
protected void failed(Throwable e, Description description) {
System.err.println(testEnvironment.getDiagnostics());
testEnvironment.close();
}
};
void close()
shutdownNow()
and awaitTermination(long, TimeUnit)
.Worker.Factory getWorkerFactory()
void start()
boolean isStarted()
start()
called?boolean isShutdown()
shutdownNow()
or shutdown()
called?boolean isTerminated()
shutdownNow()
or shutdown()
?void shutdown()
Activity.heartbeat(Object)
start throwing ActivityWorkerShutdownException
. Invocation has no additional effect
if already shut down. This method does not wait for previously received tasks to complete
execution. Use awaitTermination(long, TimeUnit)
to do that.void shutdownNow()
Activity.heartbeat(Object)
start throwing ActivityWorkerShutdownException
. Invocation has
no additional effect if already shut down. This method does not wait for previously received
tasks to complete execution. Use awaitTermination(long, TimeUnit)
to do that.void awaitTermination(long timeout, java.util.concurrent.TimeUnit unit)