# Integration Testing For Java-SDK

**URL:** <https://community.temporal.io/t/integration-testing-for-java-sdk/7047>\
**Category:** Community Support\
**Tags:** java-sdk\
**Created:** [January 24, 2023, 7:44pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047 "2023-01-24T19:44:18Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![sriramg](https://avatars.discourse-cdn.com/v4/letter/s/7ba0ec/32.png) [@sriramg](https://community.temporal.io/u/sriramg)\
**Post date:** [January 24, 2023, 7:44pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/1 "2023-01-24T19:44:18Z")

</div>

Hi Team,

I have few questions about integration testing of my temporal workflow.

My temporal workflow method has 4 activities (all blocking) with 2 activities getting data from 2 different endpoints via RPC and remaining 2 activities store data from these endpoints inside the db.  
This workflow instance is started using the temporal client from a service class (this class resides inside the same service that hosts the workflow).

I was able to unit test my temporal workflow method successfully by using the TestWorkflowExtension by mocking all of the 4 activities inside my activity implementation class.

Now for integration testing, I want to test the complete interaction from the service class that creates an instance of the workflow i.e I want to assert on the data stored inside the db as a part of this test. I have registered an actual instance of my activity implementation class (unlike in unit testing where I registered a mock impl with worker itself). I have made sure to mock the response of the 2 RPCs calls made from 2 of the activities.  
I tried using TestWorkflowExtension for this but I see that the worker from this TestWorkflowEnvironment only polls workflow tasks and my activity tasks are not starting. I guess this is expected behavior when using this TestWorkflowExtension?

I have gone through many of the discussions here and the github java samples but I do not see anything tied to something like what I want above. Most of the tests are mocking all of the activities in a workflow.

Is there a way to truly test the full interaction without mocking all the activities? Also when I look at the definition of integration testing [here](https://docs.temporal.io/application-development/testing?lang=go#assert-in-workflow) it does say mock activities and start workflow using the client.

Any help will be really appreciated.

---

<div class="post-metadata">

**Author:** ![maxim](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/maxim/32/8_2.png) [@maxim](https://community.temporal.io/u/maxim)\
**Post date:** [January 24, 2023, 8:21pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/2 "2023-01-24T20:21:31Z")

</div>

Note that TestWorkflowExtension doesn’t know anything about mocking. From its point of view, you register an activity implementation. So the non-mocked activity should work fine with it.

Look at TripBookingWorkflowTest. It registers normal activity implementations [here](https://github.com/temporalio/samples-java/blob/a551947db6d742f288c3961e2f41f2afd196757b/src/test/java/io/temporal/samples/bookingsaga/TripBookingWorkflowTest.java#L49).

---

<div class="post-metadata">

**Author:** ![sriramg](https://avatars.discourse-cdn.com/v4/letter/s/7ba0ec/32.png) [@sriramg](https://community.temporal.io/u/sriramg)\
**Post date:** [January 24, 2023, 9:30pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/3 "2023-01-24T21:30:28Z")

</div>

I looked at the example you pointed out. There is a subtle difference between what I am trying to do and what the example is doing. The example is creating the workflow instance using the client in the same task queue as the worker from the test environment.  
In my case the client creates the workflow instance from the service class in a specific task queue called `expense-category` but I see the worker that gets created in the TestWorkFlowEnvironment is not this and hence I do not see any of my workflow tasks being polled.  
I tried setting the test environment’s worker to use this queue but still same result but just that it retried the workflow task twice. Not sure what I am missing. I will paste snippets of what I am doing below.

---

<div class="post-metadata">

**Author:** ![maxim](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/maxim/32/8_2.png) [@maxim](https://community.temporal.io/u/maxim)\
**Post date:** [January 24, 2023, 9:36pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/4 "2023-01-24T21:36:01Z")

</div>

I see. It looks like we need to extend TestWorkflowExtension to support specifying your task queue name.  
For now you have to use TestWorkflowEnvironment directly and create worker for your task queue explicitly. Here is a [test](https://github.com/temporalio/sdk-java/blob/37a0e463fae2312882b5c946f423a0dbf85f9666/temporal-sdk/src/test/java/io/temporal/authorization/AuthorizationTokenTest.java#L113) that uses this approach.

---

<div class="post-metadata">

**Author:** ![maxim](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/maxim/32/8_2.png) [@maxim](https://community.temporal.io/u/maxim)\
**Post date:** [January 24, 2023, 9:36pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/5 "2023-01-24T21:36:26Z")

</div>

Please file an issue to get this added to the TestWorkflowExtension.

---

<div class="post-metadata">

**Author:** ![sriramg](https://avatars.discourse-cdn.com/v4/letter/s/7ba0ec/32.png) [@sriramg](https://community.temporal.io/u/sriramg)\
**Post date:** [January 24, 2023, 9:38pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/6 "2023-01-24T21:38:42Z")

</div>

Workflow Method

```auto
override fun automateExpenseCategory(expense: ExpenseInputDTO) {
        logger.info("automating category for expense: ${expense.expenseId}")
  // RPC
  val mcc = activity.getMccForExpense(GetMccForExpenseInputDTO(expense.accountId,
  UUID.fromString(expense.transactionId)))
  activity.insertMccForExpense(InsertMccForExpenseInputDTO(expense.expenseId, expense.accountId, mcc,
  Instant.ofEpochMilli(Workflow.currentTimeMillis())))
  val categoryId = activity.getCategoriesForExpense(GetCategoriesForExpenseInputDTO(expense.expenseId,
  expense.accountId, mcc)).first().categoryId
  //RPC
  if (activity.setCategoryForExpense(SetCategoryForExpenseInputDTO(expense.accountId, expense.expenseId,
    categoryId))) {
  activity.insertExpenseAutomationEvent(ExpenseAutomationEventDTO(expense.expenseId, expense.accountId,
    FieldName.EXPENSE_CATEGORY, categoryId.toString(), Workflow.DEFAULT_VERSION.toString(),
    Instant.ofEpochMilli(Workflow.currentTimeMillis())))
        }
    }

```

Class creating the workflow Instance

```auto
class ExpenseCategorizationServiceImpl(
    private val expenseCategoryService: ExpenseCategoryService,
    private val workflowClient: WorkflowClient
) : ExpenseCategorizationService {
    override fun automateExpense(expense: ExpenseInputDTO) {
 
val expenseCategoryWorkflowRequest = workflowClient.newWorkflowStub(
    ExpenseCategoryWorkflow::class.java,
    WorkflowOptions.newBuilder().setTaskQueue("expense-category")
        .setWorkflowId("expense-category-${expense.expenseId}")
        .setWorkflowExecutionTimeout(Duration.ZERO) // execution doesn't timeout, but fails on error
        .setWorkflowRunTimeout(Duration.ZERO)
            // prevent running the workflow for a same expense twice
        .setWorkflowIdReusePolicy(WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE_FAILED_ONLY)
        .build()
)
WorkflowClient.execute(expenseCategoryWorkflowRequest::automateExpenseCategory, expense)
      }
}

```

Test Snippet

```auto

@RegisterExtension
@JvmField
val testWorkflowExtension: TestWorkflowExtension = TestWorkflowExtension.newBuilder()
    .setWorkflowTypes(ExpenseCategoryWorkflowImpl::class.java)
    .setDoNotStart(true)
    .build()

  @Test
  fun `should automate expense category successfully`
          (testEnv: TestWorkflowEnvironment, worker: Worker, workflow: ExpenseCategoryWorkflow) {
    
// mocking the RPC calls from 2 of the activities            
   whenever(transactionViewsServiceRpc.getTransaction(any(), any())).thenReturn(cardTransaction)
  whenever(setDefaultCategoryRpc.setExpenseCategory(any())).thenReturn(true)

  val worker = testEnv.newWorker("expense-category")
  worker.registerWorkflowImplementationTypes(ExpenseCategoryWorkflowImpl::class.java)
  worker.registerActivitiesImplementations(expenseCategoryActivityImpl) // instance of activity impl
  testEnv.start()

assertDoesNotThrow { expenseCategorizationServiceImpl.automateExpense(expenseInputDTO) }
// this is the assertion on checking the data from db.
assertThat(expenseCategoryMapper.getMccAndCategoryForExpense(TestFixtures.expenseId)?.mcc)
    .isEqualTo(TestFixtures.mcc)
              }
          }
      }

```

---

<div class="post-metadata">

**Author:** ![maxim](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/maxim/32/8_2.png) [@maxim](https://community.temporal.io/u/maxim)\
**Post date:** [January 24, 2023, 9:41pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/7 "2023-01-24T21:41:32Z")

</div>

Is it a question or a working example?

---

<div class="post-metadata">

**Author:** ![sriramg](https://avatars.discourse-cdn.com/v4/letter/s/7ba0ec/32.png) [@sriramg](https://community.temporal.io/u/sriramg)\
**Post date:** [January 24, 2023, 9:45pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/8 "2023-01-24T21:45:37Z")

</div>

Wanted to post what I have. I just saw your comment about not being able to set my task queue in TestWorkflowExtension and hence the workers aren’t polling from the right queue. In fact I am creating a new worker with my task queue from the TestEnvironment as you see in the code snippet and it still doesnt work.

---

<div class="post-metadata">

**Author:** ![sriramg](https://avatars.discourse-cdn.com/v4/letter/s/7ba0ec/32.png) [@sriramg](https://community.temporal.io/u/sriramg)\
**Post date:** [January 24, 2023, 9:54pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/9 "2023-01-24T21:54:16Z")

</div>

Just to confirm, are you saying I do not use TestWorkflowExtension at all and just use TestWorkflowEnvironment like the sample you posted? The reason I ask is, if you look at my test snippet, I am setting my task queue on the worker I grab from TestWorkflowEnvironment but difference is that my test environment is managed by the TestWorkflowEnvironment. Is that where the issue is?

---

<div class="post-metadata">

**Author:** ![maxim](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/maxim/32/8_2.png) [@maxim](https://community.temporal.io/u/maxim)\
**Post date:** [January 24, 2023, 10:14pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/10 "2023-01-24T22:14:17Z")

</div>

I think your approach should work as well.

---

<div class="post-metadata">

**Author:** ![sriramg](https://avatars.discourse-cdn.com/v4/letter/s/7ba0ec/32.png) [@sriramg](https://community.temporal.io/u/sriramg)\
**Post date:** [January 24, 2023, 11:34pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/11 "2023-01-24T23:34:04Z")

</div>

Ok I think I figured the issue. Given that I was using `WorkflowClient.execute(expenseCategoryWorkflowRequest::automateExpenseCategory, expense)` which is async, my test code moved on and went to assertion. If my workflow didn’t complete by then my assertion was failing. I put a thread sleep in my test code before assertion (after `assertDoesNotThrow { expenseCategorizationServiceImpl.automateExpense(expenseInputDTO) }` in my test snippet) and then my assertions worked. I do not want to put thread.sleep in my integration test before assertions. Is there a cleaner way to wait for my service calling the workflow which is async to finish before asserting? Like can I make any blocking call on the testEnv object before asserting?

---

<div class="post-metadata">

**Author:** ![maxim](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/maxim/32/8_2.png) [@maxim](https://community.temporal.io/u/maxim)\
**Post date:** [January 25, 2023, 12:02am UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/12 "2023-01-25T00:02:02Z")

</div>

`testEnv.sleep` is the way to go. It supports time skipping. So even if your workflow is long-running, you can still test it.

---

<div class="post-metadata">

**Author:** ![sriramg](https://avatars.discourse-cdn.com/v4/letter/s/7ba0ec/32.png) [@sriramg](https://community.temporal.io/u/sriramg)\
**Post date:** [January 25, 2023, 12:16am UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/13 "2023-01-25T00:16:30Z")

</div>

Sweet. Thank you Maxim. I guess testEnv.sleep more or less becomes integral whenever we test a workflow that is async or is long running in nature.

---

<div class="post-metadata">

**Author:** ![Bohdan](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/bohdan/32/1782_2.png) [@Bohdan](https://community.temporal.io/u/Bohdan)\
**Post date:** [May 14, 2024, 12:18pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/14 "2024-05-14T12:18:17Z")

</div>

Hello @maxim  
Was TestWorkflowExtension updated to be able to specify custom task queue for a worker?  
I still can not find a way how to do it.

---

<div class="post-metadata">

**Author:** ![Bohdan](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/bohdan/32/1782_2.png) [@Bohdan](https://community.temporal.io/u/Bohdan)\
**Post date:** [May 14, 2024, 12:24pm UTC](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/15 "2024-05-14T12:24:36Z")

</div>

I submitted enhancement request if it is not supported yet

> <https://github.com/temporalio/temporal/issues/5919>
>
> \*\*Is your feature request related to a problem? Please describe.\*\*
> As discussed… in the following conversation https://community.temporal.io/t/integration-testing-for-java-sdk/7047/4?u=bohdan
> it would be nice to have possibility to specify custom name for a worker queue when using TestWorkflowExtension.
> 
> \*\*Describe the solution you'd like\*\*
> TestWorkflowExtension builder to have a setter for the worker taskQueueName. e.g. .setWorkerTaskQueue(TASK\_QUEUE)
> 
> \*\*Describe alternatives you've considered\*\*
> 
> \*\*Additional context\*\*
> \[Add any other context or screenshots about the feature request here.\](https://community.temporal.io/t/integration-testing-for-java-sdk/7047/4?u=bohdan)
