June 2008 - Posts
In a previous blog post I demonstrated how TypeMock allowed us to mock out the workflow runtime infrastructure and create true unit tests for a workflow activity. Now this may not seems like a big deal but because most of the classes in the workflow runtime are sealed mocking them with another mocking framework is pretty much impossible. Now you can test custom activities by wrapping them in a test workflow, creating a workflow runtime, running the workflow and inspecting the result I can hardly call this a unit test as we have to create lots of, complex, depended objects. So TypeMock really opens up some new possibilities here.
But the previous examples where still pretty simple, although mocking the ActivityExecutionContext has always been considered impossible, so lets try something more complicated in the shape of an asynchronous activity. Basically an asynchronous activity is an activity that returns ActivityExecutionStatus.Executing from the Execute method indicating to the workflow runtime that it isn't done yet. The activity uses ActivityExecutionContext at a later point in time to indicate that it is done by calling the CloseActivity function.
Lets take a quick look at our new activity.
public partial class WriteLineActivity3 : Activity
{
public WriteLineActivity3()
{
InitializeComponent();
}
public string Message { get; set; }
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
ActivityExecutionStatus result = ActivityExecutionStatus.Closed;
if (!string.IsNullOrEmpty(Message))
{
IComparable queueName = Guid.NewGuid();
WorkflowQueuingService wqs = executionContext.GetService<WorkflowQueuingService>();
WorkflowQueue queue = wqs.CreateWorkflowQueue(queueName, true);
queue.QueueItemAvailable += new EventHandler<QueueEventArgs>(queue_QueueItemAvailable);
WriteLineService3 service = executionContext.GetService<WriteLineService3>();
service.WriteLine(Message, queueName);
result = ActivityExecutionStatus.Executing;
}
return result;
}
void queue_QueueItemAvailable(object sender, QueueEventArgs e)
{
ActivityExecutionContext executionContext = sender as ActivityExecutionContext;
executionContext.CloseActivity();
}
}
In this case the return value from the Execute depends on the Message property being filled or not so we need to test this. First a simple test for an activity with an empty message:
/// <summary>
///A test for Execute
///</summary>
[TestMethod()]
[DeploymentItem("WFUnitTest1.exe")]
[VerifyMocks()]
public void ExecuteTestEmpty()
{
WriteLineActivity3_Accessor target = new WriteLineActivity3_Accessor();
ActivityExecutionStatus expected = ActivityExecutionStatus.Closed;
ActivityExecutionStatus actual;
ActivityExecutionContext executionContext =
RecorderManager.CreateMockedObject<ActivityExecutionContext>();
WorkflowQueuingService wqs = RecorderManager.CreateMockedObject<WorkflowQueuingService>();
WorkflowQueue queue = RecorderManager.CreateMockedObject<WorkflowQueue>();
WriteLineService3 service = RecorderManager.CreateMockedObject<WriteLineService3>();
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
executionContext.GetService<WriteLineService3>();
recorder.FailWhenCalled();
}
target.Message = "";
actual = target.Execute(executionContext);
Assert.AreEqual(expected, actual);
}
In this test I actually check that the runtime service, called WriteLineService3 in this case, is never retrieved. This test is still pretty simple and no more complicated than the test we did previously.
Lets take a look at something more complicated. The following test has the Message property set so it is expected to call the runtime service. But being an asynchronous activity it is also required to create a WorkflowQueue and bind to its QueueItemAvailable event so we will check that has happened. Finally this time the Execute function should return a status of ActivityExecutionStatus.Executing as it isn't done yet. This test runs like this:
/// <summary>
///A test for Execute
///</summary>
[TestMethod()]
[DeploymentItem("WFUnitTest1.exe")]
[VerifyMocks()]
public void ExecuteTestStart()
{
WriteLineActivity3_Accessor target = new WriteLineActivity3_Accessor();
ActivityExecutionStatus expected = ActivityExecutionStatus.Executing;
ActivityExecutionStatus actual;
ActivityExecutionContext executionContext =
RecorderManager.CreateMockedObject<ActivityExecutionContext>();
WorkflowQueuingService wqs = RecorderManager.CreateMockedObject<WorkflowQueuingService>();
WorkflowQueue queue = RecorderManager.CreateMockedObject<WorkflowQueue>();
WriteLineService3 service = RecorderManager.CreateMockedObject<WriteLineService3>();
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
// Record methods here
executionContext.GetService<WorkflowQueuingService>();
recorder.Return(wqs);
wqs.CreateWorkflowQueue(null, true);
recorder.Return(queue);
queue.QueueItemAvailable += delegate(object sender, QueueEventArgs e) { };
executionContext.GetService<WriteLineService3>();
recorder.Return(service);
service.WriteLine(null, null);
}
target.Message = "A message";
actual = target.Execute(executionContext);
Assert.AreEqual(expected, actual);
A little more complicated than the previous check but not bad at all
In this case we are binding to the QueueItemAvailable event so we need to add another test for the event handler and make sure it informs the workflow runtime we are done.
/// <summary>
///A test for queue_QueueItemAvailable
///</summary>
[TestMethod()]
[DeploymentItem("WFUnitTest1.exe")]
[VerifyMocks()]
public void queue_QueueItemAvailableTest()
{
WriteLineActivity3_Accessor target = new WriteLineActivity3_Accessor();
QueueEventArgs e = null; // TODO: Initialize to an appropriate value
ActivityExecutionContext executionContext =
RecorderManager.CreateMockedObject<ActivityExecutionContext>();
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
executionContext.CloseActivity();
}
target.queue_QueueItemAvailable(executionContext, e);
}
Not bad at all 
That leaves us with writing a unit test for the runtime service itself. This runtime service actually looks like this:
public class WriteLineService3: WorkflowRuntimeService
{
public void WriteLine(string message, IComparable queueName)
{
Guid instanceId = WorkflowEnvironment.WorkflowInstanceId;
ThreadPool.QueueUserWorkItem(state => WriteLineAsync(message, instanceId, queueName));
}
private void WriteLineAsync(string message, Guid instanceId, IComparable queueName)
{
Thread.Sleep(TimeSpan.FromSeconds(5));
Console.WriteLine(message);
WorkflowInstance instance = GetWorkflow(instanceId);
instance.EnqueueItem(queueName, null, null, null);
}
private WorkflowInstance GetWorkflow(Guid instanceId)
{
WorkflowInstance result = Runtime.GetWorkflow(instanceId);
return result;
}
}
Not very complicated or realistic for that matter but still lets write a quick unit test for it like this:
/// <summary>
///A test for WriteLine
///</summary>
[TestMethod()]
[VerifyMocks(10000)]
public void WriteLineTest()
{
WriteLineService3_Accessor target = new WriteLineService3_Accessor();
string message = string.Empty; // TODO: Initialize to an appropriate value
IComparable queueName = null; // TODO: Initialize to an appropriate value
WorkflowInstance instance = RecorderManager.CreateMockedObject<WorkflowInstance>();
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
Guid instanceId = WorkflowEnvironment.WorkflowInstanceId;
recorder.Return(Guid.NewGuid());
target.GetWorkflow(instanceId);
recorder.Return(instance);
instance.EnqueueItem(null, null, null, null);
}
target.WriteLine(message, queueName);
}
The most important thing here is that we can mock the WorkflowInstance object just as easy as the ActivityExecutionContext in the previous tests. I am actually telling TypeMock to wait for 10 seconds with the [VerifyMocks(10000)] attribute. This allows the delay in the service to remain there and still check if the expected response was queued. One thing to note is that I had to create an extra GetWorkflow() function to wrap the real function on the WorkflowRuntime object. I was unable to mock the latter however I am unsure why this is the case and if mocking it is really impossible.
Enjoy!
www.TheProblemSolver.nl
http://wiki.WindowsWorkflowFoundation.eu
Using an ActivityDesignerTheme is a quick way to customize the appearance of an activity in the workflow designer. But there is a gotcha
Because once you applied the theme and have a workflow with the custom activity open in the designer no matter what you do changes will not be applied.
I am not sure why this is but I suppose the designer caches the color scheme and doesn't see any changes made to it.
Take the following activity:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Drawing.Drawing2D;
namespace WorkflowConsoleApplication4
{
[Designer(typeof(MyActivity1ActivityDesigner))]
public partial class MyActivity: Activity
{
}
[ActivityDesignerTheme(typeof(MyActivity1ActivityDesignerTheme))]
public class MyActivity1ActivityDesigner: ActivityDesigner
{
}
public class MyActivity1ActivityDesignerTheme : ActivityDesignerTheme
{
/// <summary>
/// Initializes a new instance of the MyActivity1ActivityDesignerTheme class.
/// </summary>
public MyActivity1ActivityDesignerTheme(WorkflowTheme theme)
: base(theme)
{
BackColorStart = Color.LightBlue;
BackColorEnd = Color.Blue;
BackgroundStyle = LinearGradientMode.ForwardDiagonal;
}
}
}
Which look like this in the designer
Clearly the background has a blue gradient. Now if I change the theme code to the following:
public class MyActivity1ActivityDesignerTheme : ActivityDesignerTheme
{
/// <summary>
/// Initializes a new instance of the MyActivity1ActivityDesignerTheme class.
/// </summary>
public MyActivity1ActivityDesignerTheme(WorkflowTheme theme)
: base(theme)
{
BackColorStart = Color.LightCyan;
BackColorEnd = Color.Cyan;
BackgroundStyle = LinearGradientMode.ForwardDiagonal;
}
}
You might expect the activity to change its look to:
Unfortunately this doesn't happen 
Now you can quit Visual Studio and restart it after which the new style will take affect but there is a quicker way. Right click the activity and select "Select Custom Theme..."
When the dialog shows just click OK and the designer reads the theme again 
Enjoy!
www.TheProblemSolver.nl
http://wiki.WindowsWorkflowFoundation.eu
When working with state machine workflow's the SetStateActivity is one of the more important activities to use. The main reason is that is the one used to transition from one state to another. You can actually transition state in a different way as well using the StateMachineWorkflowInstance.SetState() function but the SetStateActivity is by far the most often used.
One of the cool features of the SetStateActivity that may not be immediately obvious is the fact that it doesn't do the state switch immediately. Instead it saved the new target start in an internal property, named NextStateName on the StateMachineExecutionState type to be exact, and only does the state switch when the current EventDrivenActivity or StateInitializationActivity is finished. And just to be clear those are the only two activities where you can use a SetStateActivity.
So the cool part is that you don't need to have the SetStateActivity right at the bottom of the EventDrivenActivity but it can be anywhere in the execution flow. Something that might make the execution logic quite a bit easier.
And the second cool behavior is that you can actually execute multiple SetStateActivity objects with different TargetStateName definitions and only the last one will be executed. Again something that might make the logic quite a bit simple as you can set a default TargetStateName at the beginning of your and make changes to the target as exceptional cases arise.
Both of these behaviors are especially important as the TargetStateName is a meta property, meaning it cannot be changed at runtime but only at design time. So the option of dynamically changing the SetStateActivity doesn't really exist.
Enjoy!
www.TheProblemSolver.nl
http://wiki.WindowsWorkflowFoundation.eu
I just heard about a pretty nasty "bug" with ClickOnce. Well it isn't an actual bug but still a nasty problem to run into.
The problem is actually with the certificate used to sign a ClickOnce installer. When you create a new ClickOnce installer Visual Studio will automatically generate the required certificate for you. And the intention was that this was only a temporary certificate and that a developer would replace it with a real one. Now it turns out that most people, including me, think there is only a single advantage to using a real and that is the claim that the certificate is from an untrusted publisher. Well that is only a warning most people ignore anyway so why bother with the real certificate.
Well it turns out there is a second, much larger, disadvantage to using the generated certificate. And that is the fact that it is only valid for a single year. And after that year the ClickOnce installation will stop downloading new updates.
More information, including a workaround, can be found here.
Thanks to Eric Knox and Cory Smith for pointing this out.
Enjoy!
Most people consider unit testing of custom workflow activities to pretty much impossible. Sure you can create a dummy test workflow containing your new activity, new up a WorkflowRuntime, create a WorkflowInstance and start it. But just think about all the dependencies here with the extra dummy workflow and the complete WorkflowRuntime with all its dependencies. Hardly a unit test for an activity but more like an integration test. Now there is nothing wrong with integration tests, they are very useful and necessary, but they do not give the speedy and dynamic test coverage you expect and need from a unit test.
So is this really the case?
Lets look at a few simple examples. This first example is really simple, in fact simple enough to say unrealistic but lets take a look anyway:
public partial class WriteLineActivity1 : Activity
{
public WriteLineActivity1()
{
InitializeComponent();
}
public string Message { get; set; }
protected override ActivityExecutionStatus Execute(
ActivityExecutionContext executionContext)
{
if (!string.IsNullOrEmpty(Message))
Console.WriteLine(Message);
return ActivityExecutionStatus.Closed;
}
}
This can easily be tested with a unit test like this.
/// <summary>
///A test for Execute
///</summary>
[TestMethod()]
[DeploymentItem("WFUnitTest1.exe")]
public void ExecuteTest()
{
WriteLineActivity1_Accessor target =
new WriteLineActivity1_Accessor();
ActivityExecutionContext executionContext = null;
ActivityExecutionStatus expected = ActivityExecutionStatus.Closed;
ActivityExecutionStatus actual;
actual = target.Execute(executionContext);
Assert.AreEqual(expected, actual);
}
So that at least proves some activities can be unit tested 
But admittedly this is an oversimplification. In a more realistic activity the actual Console.WriteLine(), or whatever the activity needs done, would be implemented in a workflow runtime service so its implementation can be changed independently of the workflow. And that means using the ActivityExecutionContext to retrieve a reference to the service.
Now this is where most people stop because the ActivityExecutionContext is a sealed type and sealed types cannot be mocked! But that isn't quite true because TypeMock can mock just about anything!
So lets take look at slightly more realistic sample.
public partial class WriteLineActivity2: Activity
{
public WriteLineActivity2()
{
InitializeComponent();
}
public string Message { get; set; }
protected override ActivityExecutionStatus Execute(
ActivityExecutionContext executionContext)
{
if (!string.IsNullOrEmpty(Message))
{
WriteLineService2 service =
executionContext.GetService<WriteLineService2>();
service.WriteLine(Message);
}
return ActivityExecutionStatus.Closed;
}
}
This activity does the same job as the first one but delegates the actual work to this, simple, runtime service:
public class WriteLineService2
{
public void WriteLine(string message)
{
Console.WriteLine(message);
}
}
So lets create a few unit tests for this activity. The first test checks the behavior when the message is empty:
/// <summary>
///A test for Execute
///</summary>
[TestMethod()]
[DeploymentItem("WFUnitTest1.exe")]
[VerifyMocks()]
public void ExecuteTestNoMessage()
{
WriteLineActivity2_Accessor target = new WriteLineActivity2_Accessor();
ActivityExecutionContext executionContext = null;
ActivityExecutionStatus expected = ActivityExecutionStatus.Closed;
ActivityExecutionStatus actual;
actual = target.Execute(executionContext);
Assert.AreEqual(expected, actual);
}
Still pretty simple because there is no interaction between the activity and the ActivityExecutionContext. But what happens the message is filled?
/// <summary>
///A test for Execute
///</summary>
[TestMethod()]
[DeploymentItem("WFUnitTest1.exe")]
[VerifyMocks()]
public void ExecuteTestWithMessage()
{
WriteLineActivity2_Accessor target = new WriteLineActivity2_Accessor();
ActivityExecutionStatus expected = ActivityExecutionStatus.Closed;
ActivityExecutionStatus actual;
ActivityExecutionContext executionContext =
RecorderManager.CreateMockedObject<ActivityExecutionContext>();
WriteLineService2 service =
RecorderManager.CreateMockedObject<WriteLineService2>();
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
// Record methods here
service.WriteLine(null);
executionContext.GetService<WriteLineService2>();
recorder.Return(service);
}
target.Message = "A message";
actual = target.Execute(executionContext);
Assert.AreEqual(expected, actual);
}
In this case we are mocking the ActivityExecutionContext using the RecorderManager.CreateMockedObject<ActivityExecutionContext>() statement. And this mock ActivityExecutionContext returns a mock WriteLineService2 when asked, pretty cool right? 
Now I won't claim to know every mocking framework out there but as far as I know TypeMock is the only one that can to this and create proper unit test for a custom workflow activity.
Enjoy!
www.TheProblemSolver.nl
http://wiki.WindowsWorkflowFoundation.eu