This morning I’ve been working on how to support cancelling a workflow via a CancellationToken. The details of that are not important right now but what is really cool is how I was able to test this.
Scenario: Caller requests Cancellation via a CancellationToken and the UnhandledExceptionAction is Cancel
- An activity that contains a CancellationScope
- The CancellationScope body has an activity that will create a bookmark and go idle
- The CancellationScope has a CancelHandler with a WriteLine that has a DisplayName "CancelHandlerWriteLine"
- The caller invokes the workflow asynchronously as a task with a CancellationToken
- and in the idle callback calls CancellationTokenSource.Cancel
- A TaskCanceledException is thrown
- The WorkflowApplication is canceled
- The CancelationScope CancelHandler is invoked
- How can I wait until the cancel is completed after handling the exception before verifying?
- How will I verify that the CancelHandler is invoked?
To wait until the cancel is completed after handling the exception before verifying I simply create an AutoResetEvent (line 18) and signal it from the WorkflowApplication.Completed event callback (line 19). Then before verifying the tracking data I wait for this event (line 41)
To verify that the cancel handler was invoked I use the Microsoft.Activities.UnitTesting.Tracking.MemoryTrackingParticipant. This allows me to capture the tracking information into a collection that I can search using AssertTracking.Exists to verify that the activity with the name ExpectedCancelWriteline entered the Closed state.
When I run this test I also get the Tracking info in the Test Results along with any Debug.WriteLine output to help me sort out what is happening. The tracking data is nicely formatted thanks to extension methods in Microsoft.Activities.UnitTesting.Tracking that provide a Trace method for each type of tracking record which produces human readable formatting.