How To Unit Test Workflows–Mocking Activities

Suppose you want to unit test a workflow that has some external dependency like a database, web service, file or some other thing that makes testing inconvenient.  The need to eliminate external dependencies when testing has led to a world of mocking frameworks that allow you to automatically generate a mock with pre-defined behavior.

I wanted to do the same thing with Activities in workflows and I’ve now added support for this to the latest release of the Workflow Test Helper project using a technique I call XAML Injection.  The idea is that you deploy the .xaml file for your activity and the XamlInjector class uses it as input to create a test version of the XAML with the mock classes instead of the real ones.

For example, here is a test activity that calculates a sum of numbers returned from the various test activities.  Each test activity returns the number at the end of its name so TestActivity1 will return 1.

image

Without Xaml Injection the calculated sum for this activity should be 1+1+1+4+4=13.

Suppose I wanted to replace some of the activities with special Mock activities.  In that case I create Mock activities that have the same “interface” (Properties and In/Out arguments) as the activity they are mocking.

Then I create a XamlInjector and tell it about the activity types I want to replace.  In the following example I’m going to leave the first instance of TestActivity1 in place, replace the second with TestActivity2 and the third with TestActivity3 and I want to replace all instances of TestActivity4 with TestActivity5.  The resulting test version of the activity will calculate a sum of 1+2+3+5+5=16.

 [TestMethod]

[DeploymentItem(@"WorkflowTestHelper.Tests\TestInject.xaml")]

public void ShouldReplaceTypesInXaml()

{

    var xamlInjector = new XamlInjector("TestInject.xaml");



    // The first TestActivity1 will not be replaced - will add 1 to sum



    // Replace the second TestActivity1 with TestActivity2 - will add 2 to sum

    xamlInjector.ReplaceAt(1, typeof (TestActivity1), typeof (TestActivity2));



    // Replace third TestActivity1 with TestActivity3 - will add 3 to sum

    xamlInjector.ReplaceAt(2, typeof (TestActivity1), typeof (TestActivity3));



    // Replace all (2) TestActivity4 with TestActivity5 - will add 10 to sum

    xamlInjector.ReplaceAll(typeof (TestActivity4), typeof (TestActivity5));

    var activity = xamlInjector.GetActivity();



    Debug.WriteLine(string.Format("Invoking Injected XAML activity {0}", activity.GetType()));



    var wiTest = new WorkflowInvokerTest(activity);



    // Act

    wiTest.TestActivity();



    // Total should be 1+2+3+10=16

    wiTest.AssertOutArgument.AreEqual("sum", 16);

}

Special thanks to Dan Glick for helping me with the XamlReader/Writer code in this release. 

Check it out – download Workflow Test Helper today!