Testing SharePoint Workflows using TypeMock Isolator (Part 2)

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:       /// <param name="wfType">The type of workflow to create</param>
  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<SPWorkflowActivationProperties>().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.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>