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().With(fakeProperties);

 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.