Search code examples
javaunit-testingamazon-swf

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?


Solution

  • 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();
    }