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: \[TestMethod\]
2: public void WorkFlowSwitchOnTitle_TitleStartsWithA_SetApprovelFieldAndUpdate()
3: {
4: // Arrange
5: var fakeProperties = Isolate.Fake.Instance<SPWorkflowActivationProperties>();
6: var fakeItem = fakeProperties.Item;
7: Isolate.WhenCalled(() => fakeItem.Title).WillReturn("ABC");
8:
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
11: /\*
12: var fakeField = fakeItem.Fields[“Approved”];
13: fakeField.DefaultValue = false.ToString();
14: */
15:
16: // Act
17: WorkflowRunner(typeof(SharePointWorkflow.Workflow1),fakeProperties);
18:
19: // Assert
20: Isolate.Verify.WasCalledWithExactArguments(() => fakeItem.Update());
21: Isolate.Verify.WasCalledWithExactArguments(() => fakeItem\["Approved"\] = "True");
22:
23: }
24:
25: \[TestMethod\]
26: public void WorkFlowSwitchOnTitle_TitleStartsWithZ_DoNothing()
27: {
28: // Arrange
29: var fakeProperties = Isolate.Fake.Instance<SPWorkflowActivationProperties>();
30: var fakeItem = fakeProperties.Item;
31: Isolate.WhenCalled(() => fakeItem.Title).WillReturn("XYZ");
32:
33: // Act
34: WorkflowRunner(typeof(SharePointWorkflow.Workflow1),fakeProperties);
35:
36: // Assert
37: Isolate.Verify.WasNotCalled(() => fakeItem.Update());
38:
39: }
40:
41:
42:
43: /// <summary>
44: /// A helper method to run a workflow for a test
45: /// </summary>
46: /// The type of workflow to create
47: /// <param name="fakeProperties">The fake properties used to create the workflow</param>
48: private static void WorkflowRunner(Type wfType, SPWorkflowActivationProperties fakeProperties)
49: {
50: using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
51: {
52: AutoResetEvent waitHandle = new AutoResetEvent(false);
53: workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
54: {
55: // don't put asserts here as will be in the wrong thread
56: waitHandle.Set();
57: };
58:
59: workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
60: {
61: // don't put asserts here as will be in the wrong thread
62: waitHandle.Set();
63: };
64:
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
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
69: WorkflowInstance instance = workflowRuntime.CreateWorkflow(wfType);
70:
71: // SO for this reason we only get the swap after the first create has beend one
72: Isolate.Swap.NextInstance
73:
74: // we then recreate the workflow again, this time it has already been validated so
75: // so the swap works
76: instance = workflowRuntime.CreateWorkflow(wfType);
77:
78: instance.Start();
79:
80: waitHandle.WaitOne();
81:
82: // the workflow is finished assert could go here, but will be done
83: // in the calling method
84:
85: }
86:
87: }
```
The workflow remains the same as in the previous post.