Testing SharePoint Workflows using TypeMock Isolator
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:
- 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
- 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
private void IfTest(object sender, ConditionalEventArgs e)
{
var currentItem = workflowProperties.Item;
e.Result = currentItem.Title.StartsWith("A");
}
private void TrueTask(object sender, EventArgs e)
{
var currentItem = workflowProperties.Item;
currentItem["Approved"] = true.ToString();
currentItem.Update();
}
I then created a test using the same form I did for WF based testing, I think the comments cover the key points
[TestMethod]
public void WorkFlowSwitchOnTitle_TitleStartsWithA_SetApprovelField()
{
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
// Create our fake workflow and items
var fakeProperties = Isolate.Fake.Instance<SPWorkflowActivationProperties>(Members.ReturnRecursiveFakes);
var fakeItem = Isolate.Fake.Instance<SPListItem>(Members.ReturnRecursiveFakes);
var fakeField = Isolate.Fake.Instance<SPField>(Members.ReturnRecursiveFakes);
fakeField.DefaultValue = false.ToString();
Isolate.WhenCalled(() => fakeProperties.Item).WillReturn(fakeItem);
// setup the if test
Isolate.WhenCalled(() => fakeItem.Title).WillReturn("ABC");
Isolate.WhenCalled(() => fakeItem["Approved"]).WillReturn(fakeField);
// setup the workflow handling
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
{
// don't put asserts here as will be in the wrong thread
waitHandle.Set();
};
workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
{
// don't put asserts here as will be in the wrong thread
waitHandle.Set();
};
// when this is called the constructor is called twice
// the first time is for validation for the workflow in this appdomain see http://odetocode.com/Blogs/scott/archive/2006/03/30/3192.aspx
// then the real construction is run, the problem is this double run means that the Isolate.Swap.NextInstance
// fails as it attaches to the first validation create, not the second real one
WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(SharePointWorkflow.Workflow1));
// SO for this reason we only get the swap after the first create has been done
Isolate.Swap.NextInstance<SPWorkflowActivationProperties>().With(fakeProperties);
// we then recreate the workflow again, this time it has already been validated so
// the swap works
instance = workflowRuntime.CreateWorkflow(typeof(SharePointWorkflow.Workflow1));
instance.Start();
waitHandle.WaitOne();
// wait for the workflow to complete and then check the method expected were called
Isolate.Verify.WasCalledWithExactArguments(() => fakeItem.Update());
Isolate.Verify.WasCalledWithExactArguments(() => fakeItem["Approved"] = "True");
}
}
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
Read the complete post at http://blogs.blackmarble.co.uk/blogs/rfennell/archive/2009/04/03/testing-sharepoint-workflows-using-typemock-isolator.aspx