Allan5 Allan5 - 1 month ago 25
Java Question

Unit testing Amazon SWF child workflows

I have a parent workflow (ParentWorkflow) calling a child workflow (ChildWorkflow) and I'm trying to test out the call.

The parent code looks something like this:

public class ParentWorkflow {
private final ChildWorkflowClientFactory childWorkflowClientFactory =
new ChildWorkflowClientFactoryImpl();

public void runWorkflow() {
new TryCatch() {
@Override
protected void doTry() throws Throwable {
Promise<Void> workflowFinished = childWorkflowClient.childWorkflow(x);
...
}
...
}
}


I want to mock out the
childWorkflowClient.childWorkflow(x)

call, however when I am hooking up the unit test I don't appear to have the option to inject the client factory, the unit test code looks like this:

@Rule
public WorkflowTest workflowTest = new WorkflowTest();
@Mock
private Activities mockActivities;

private ParentWorkflowClientFactory workflowFactory
= new ParentWorkflowClientFactoryImpl();

@Before
public void setUp() throws Exception {
// set up mocks
initMocks(this);

workflowTest.addActivitiesImplementation(mockActivities);
workflowTest.addWorkflowImplementationType(ParentWorkflowImpl.class);
workflowTest.addWorkflowImplementationType(ChildWorkflowImpl.class);


I don't appear to be able to pass anything into the workflow implementation classes, is there another way I can mock the child workflow out?

Answer

You can test workflow code directly mocking its dependencies without using workflowTest:

/**
 * Rule is still needed to initialize asynchronous framework.
 */
@Rule
public WorkflowTest workflowTest = new WorkflowTest();
@Mock
private ActivitiesClient mockActivities;
@Mock
private BWorkflowClientFactory workflowFactory;


@Before
public void setUp() throws Exception {
  // set up mocks
  initMocks(this);
}

@Test
public void myTest() {
  AWorkflowImpl w = new AWorkflowImpl(workflowFactory);
  w.execute(); // whatever execute method of the workflow
}

This approach allows testing parts of the workflow encapsulated in other objects instead of the entire workflow.

If for whatever reason (for example you are using other testing framework than JUnit) you don't want to rely on WorkflowTest @Rule asynchronous code can be always executed using AsyncScope:

@Test
public void asyncTest() {
   AsyncScope scope = new AsyncScope() {
      protected void doAsync() {
         // Any asynchronous code
         AWorkflowImpl w = new AWorkflowImpl(workflowFactory);
         w.execute(); // whatever execute method of the workflow
      }
   };
   scope.eventLoop();
}