How to test starting/signaling a workflow in Java?

I’d like to test code that is attempting to signalWithStart a workflow (note: I’m not trying to test the workflow itself). The code under test has a dependency on WorkflowClient. Oversimplified example (Kotlin):

class ClientExample(
    val client: WorkflowClient,
) {
    fun sendStringAsSignal(workflowId: String, signalValue: String) {
        val workflow = client.newWorkflowStub(

How can I test that my WorkflowStub was created with the correct arguments and that the workflow signal method was invoked with the correct arguments?

I cannot easily mock the client since I would need to heavily mock multiple layers: newWorkflowStub, static WorkflowStub.fromTyped, etc.

I see that Go has a Client mock but I don’t see any similar offering in the Java SDK (maybe mocking is more idiomatic in Go?).

The simplest is to implement a workflow that validates these. Then run it using TestWorkflowEnvironment.

1 Like

Thank you. I’ll explore that approach. I suppose I could create a test-specific implementation of my real workflow interface as well.

Is there a way to name the task queue used by the TestEnvironment so that I can test which task queue I’m targeting?

You can set it through options, but I would just check against the value of Workflow.getInfo().getTaskQueue().

1 Like

Thanks again @maxim. I’m taking this approach now.

Some FYIs to anyone reading this in the future, and optionally as feedback to Temporal team:

  1. It looks like TestWorkflowExtension doesn’t currently support configuring the task queue, but you can configure task queue with testEnv.newWorker when using the manual approach.
  2. When invoking a workflow with signalWithStart, it doesn’t block for completion, nor does the returned WorkflowExecution offer an easy way to await the execution to finish. The best way that I could find was to construct a new workflow stub and to invoke the workflow in a blocking fashion.

I ultimately ended up with something like this (Kotlin):

val expectedTaskQueue = "ExpectedTaskQueue"
val testEnv = TestWorkflowEnvironment.newInstance()
val worker = testEnv.newWorker(expectedTaskQueue)
val client = testEnv.workflowClient
val myService = MyServiceImpl(client)

class TestWorkflowImpl : MyWorkflow {
    var signaled = false;

    override fun startWorkflow(input: MyWorkflowInput): MyWorkflowOutput {
        val success = Workflow.await(Duration.ofSeconds(5)) { signaled }
        if (!success) {
            throw TimeoutException("Timed out waiting for signal")
        return MyWorkflowOutput()

    override fun signal(input: SignalInput) {
        signaled = true

fun setUp() {

fun tearDown() {

@Timeout(value = 10, unit = TimeUnit.SECONDS)
fun testSubmit() {
    // Given
    val input = UUID.randomUUID().toString()

    // When
    val workflowExecution = myService.submit(input)

    // Await
    val workflowStub = client.newUntypedWorkflowStub(workflowExecution.workflowId)
    val workflowOutput = workflowStub.getResult<MyWorkflowOutput>()

    // Then

Feedback welcome on any ways to simplify this, but it is cleaner than trying to mock WorkflowClient/WorkflowStub.

You also can use an untyped stub to wait:

WorkflowStub untyped = client.newUntypedWorkflowStub(workflowExecution, Optional.of("MyWorkflow"));

Nice! Thank you. Updated my code snippet to use this approach.