in

But it works on my PC!

The random thoughts of Richard Fennell on technology and software development

This Blog

Syndication

Testing SharePoint Workflows using TypeMock Isolator

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. 

Updated 6 April 2009 – Also see Testing SharePoint Workflows using TypeMock Isolator (Part 2)

I have for a while been trying to test SharePoint workflows using TypeMock Isolator to mock out the SharePoint fixtures, I want to remove the dependency of having SharePoint on any test boxes where possible. I have at last got this working after getting a new version of TypeMock Isolator 5.3.0 + a fix from the very helpful team at TypeMock

My idea was to be able to build a workflow that could changed list item properties for a document e.g. the workflow could set a field called approved to true if certain criteria were met. Now as a MOSS2007 workflow is based on .NET WF I knew I could try to build upon the work I document in my previous post on TDD for WF.

My test system was as follows:

  1. I created a new SharePoint workflow, all it contained was a decision box that went down the true path if the document associated with the workflow has a title starting with the letter A
  2. In a coded action for the true path, I then set an approved property to true.

All very simple, but good enough for this test, the key methods are shown below

   1: private void IfTest(object sender, ConditionalEventArgs e)
   2:    {
   3:       var currentItem = workflowProperties.Item;        e.Result = currentItem.Title.StartsWith("A");
   4:    }
   5:  
   6:    private void TrueTask(object sender, EventArgs e)
   7:    {
   8:       var currentItem = workflowProperties.Item;
   9:       currentItem["Approved"] = true.ToString();
  10:       currentItem.Update();
  11:    }

I then created a test using the same form I did for WF based testing, I think the comments cover the key points

   1: [TestMethod]
   2:       public void WorkFlowSwitchOnTitle_TitleStartsWithA_SetApprovelField()
   3:       {
   4:           using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
   5:           {
   6:  
   7:               // Create our fake workflow and items
   8:               var fakeProperties = Isolate.Fake.Instance<SPWorkflowActivationProperties>(Members.ReturnRecursiveFakes);
   9:               var fakeItem = Isolate.Fake.Instance<SPListItem>(Members.ReturnRecursiveFakes);
  10:  
  11:               var fakeField = Isolate.Fake.Instance<SPField>(Members.ReturnRecursiveFakes);
  12:               fakeField.DefaultValue = false.ToString();
  13:               Isolate.WhenCalled(() => fakeProperties.Item).WillReturn(fakeItem);
  14:               // setup the if test
  15:               Isolate.WhenCalled(() => fakeItem.Title).WillReturn("ABC");
  16:               Isolate.WhenCalled(() => fakeItem["Approved"]).WillReturn(fakeField);
  17:  
  18:               // setup the workflow handling                AutoResetEvent waitHandle = new AutoResetEvent(false);
  19:               workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
  20:               {
  21:                   // don't put asserts here as will be in the wrong thread
  22:                   waitHandle.Set();
  23:               };
  24:  
  25:               workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
  26:               {
  27:                   // don't put asserts here as will be in the wrong thread
  28:                   waitHandle.Set();
  29:               };
  30:  
  31:               // when this is called the constructor is called twice
  32:               // the first time is for validation for the workflow in this appdomain see http://odetocode.com/Blogs/scott/archive/2006/03/30/3192.aspx
  33:               // then the real construction is run, the problem is this double run means that the Isolate.Swap.NextInstance
  34:               // fails as it attaches to the first validation create, not the second real one
  35:               WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(SharePointWorkflow.Workflow1));
  36:  
  37:               // SO for this reason we only get the swap after the first create has been done
  38:               Isolate.Swap.NextInstance<SPWorkflowActivationProperties>().With(fakeProperties);
  39:  
  40:               // we then recreate the workflow again, this time it has already been validated so
  41:               // the swap works
  42:               instance = workflowRuntime.CreateWorkflow(typeof(SharePointWorkflow.Workflow1));
  43:  
  44:               instance.Start();
  45:  
  46:               waitHandle.WaitOne();
  47:               // wait for the workflow to complete and then check the method expected were called                Isolate.Verify.WasCalledWithExactArguments(() => fakeItem.Update());
  48:               Isolate.Verify.WasCalledWithExactArguments(() => fakeItem["Approved"] = "True");
  49:           }
  50:  
  51:       }
 

If you try this without the fix TypeMock provided me with, the two verifies will fail, I am told this is due to a threading issue. Interesting that this is SharePoint specific as the same basic method works OK for standard WF workflows.

I also understand this fix will be in the next TypeMock release, I will update this post when I know for sure

Comments

 

Gil Zilberfeld said:

So cool! I was actually asked today if someone is really  using WF or if it was just a fad. Thanks for the example.

And thank you very much for the kind words.

Here's a tip - Members.ReturnRecursiveFakes is the default (since version 5.2), so you don't need to specify it in Fake.Instance.

April 3, 2009 7:29 PM
 

Richard said:

Have a look at Gil's post blog.typemock.com/.../writing-shorter-tests-don-build-tree.html on writing the same test in less lines of code.

April 6, 2009 10:11 PM
 

Testing SharePoint Workflows using TypeMock Isolator (Part 2) - But it works on my PC! said:

Pingback from  Testing SharePoint Workflows using TypeMock Isolator (Part 2) - But it works on my PC!

April 6, 2009 10:48 PM
 

Testing SharePoint Workflows using TypeMock Isolator (Part 2) - Richard Fennell - MSMVPS.COM said:

Pingback from  Testing SharePoint Workflows using TypeMock Isolator (Part 2) - Richard Fennell - MSMVPS.COM

April 6, 2009 11:48 PM
 

More great Unit Testing SharePoint Examples | Agile Sharepoint development by 21apps and Andrew Woodward MVP said:

Pingback from  More great Unit Testing SharePoint Examples | Agile Sharepoint development by 21apps and Andrew Woodward MVP

April 23, 2009 1:24 PM
 

Confluence: SharePoint Development Wiki said:

"unit testing is a method of testing that verifies the individual units of source code are working properly. A unit is the smallest testable part of an application. In procedural programming a unit may be an individual program, function, procedure,..

April 25, 2009 3:38 AM
 

Confluence: SharePoint Implementation Play book said:

"unit testing is a method of testing that verifies the individual units of source code are working properly. A unit is the smallest testable part of an application. In procedural programming a unit may be an individual program, function, procedure,..

January 2, 2010 4:23 AM
Black Marble 2004-2009
Powered by Community Server (Commercial Edition), by Telligent Systems