Testing SharePoint Workflows using TypeMock Isolator (Part 2)
Updated 12 June 2009 - I have been having problems using this technique of Typemock with Sharepoint Workflows, the workflows keep unexpectedly idling as opposed to activating. If you suffer similar problem please check for later posts as to any solutions I find.
After reading Gil’s blog on writing simpler tests I have done some tidying of the code from my previous post. In this version I have extracted the boiler plate code to run the workflow to a static helper method and modified my tests to incorporate Gil’s comments, they are certainly more readable.
1 1: \[TestMethod\]
2: public void WorkFlowSwitchOnTitle_TitleStartsWithA_SetApprovelFieldAndUpdate()
1 3: {
4: // Arrange
1 5: var fakeProperties = Isolate.Fake.Instance<SPWorkflowActivationProperties>();
6: var fakeItem = fakeProperties.Item;
1 7: Isolate.WhenCalled(() => fakeItem.Title).WillReturn("ABC");
8:
1 9: // we actually don't need to create this field MOSS lets us attempt to write to
10: // it even if not declared, it would only need to be created if we check the value in the workflow
1 11: /\*
12: var fakeField = fakeItem.Fields["Approved"];
1 13: fakeField.DefaultValue = false.ToString();
14: */
1 15:
16: // Act
1 17: WorkflowRunner(typeof(SharePointWorkflow.Workflow1),fakeProperties);
18:
1 19: // Assert
20: Isolate.Verify.WasCalledWithExactArguments(() => fakeItem.Update());
1 21: Isolate.Verify.WasCalledWithExactArguments(() => fakeItem\["Approved"\] = "True");
22:
1 23: }
24:
1 25: \[TestMethod\]
26: public void WorkFlowSwitchOnTitle_TitleStartsWithZ_DoNothing()
1 27: {
28: // Arrange
1 29: var fakeProperties = Isolate.Fake.Instance<SPWorkflowActivationProperties>();
30: var fakeItem = fakeProperties.Item;
1 31: Isolate.WhenCalled(() => fakeItem.Title).WillReturn("XYZ");
32:
1 33: // Act
34: WorkflowRunner(typeof(SharePointWorkflow.Workflow1),fakeProperties);
1 35:
36: // Assert
1 37: Isolate.Verify.WasNotCalled(() => fakeItem.Update());
38:
1 39: }
40:
1 41:
42:
1 43: /// <summary>
44: /// A helper method to run a workflow for a test
1 45: /// </summary>
46: /// The type of workflow to create
1 47: /// <param name="fakeProperties">The fake properties used to create the workflow</param>
48: private static void WorkflowRunner(Type wfType, SPWorkflowActivationProperties fakeProperties)
1 49: {
50: using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
1 51: {
52: AutoResetEvent waitHandle = new AutoResetEvent(false);
1 53: workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
54: {
1 55: // don't put asserts here as will be in the wrong thread
56: waitHandle.Set();
1 57: };
58:
1 59: workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
60: {
1 61: // don't put asserts here as will be in the wrong thread
62: waitHandle.Set();
1 63: };
64:
1 65: // when this is called the constructor is called twice
66: // the first time is for validation for the workflow in this appdomain see http://odetocode.com/Blogs/scott/archive/2006/03/30/3192.aspx
1 67: // then the real construction is run, the problem is this double run means that the Isolate.Swap.NextInstance
68: // fails as it attaches to the first validation create, not the second real one
1 69: WorkflowInstance instance = workflowRuntime.CreateWorkflow(wfType);
70:
1 71: // SO for this reason we only get the swap after the first create has beend one
72: Isolate.Swap.NextInstance
1 73:
74: // we then recreate the workflow again, this time it has already been validated so
1 75: // so the swap works
76: instance = workflowRuntime.CreateWorkflow(wfType);
1 77:
78: instance.Start();
1 79:
80: waitHandle.WaitOne();
1 81:
82: // the workflow is finished assert could go here, but will be done
1 83: // in the calling method
84:
1 85: }
86:
1 87: }
2```
3
4The workflow remains the same as in the previous post.