Typically, one workflow can be started with the code similar to following one:
WorkflowInstance instance; Dictionary<string, object> props = new Dictionary<string, object>(); props.Add("WorkflowArgument", "test"); instance = m_Runtime.CreateWorkflow(typeof(MyWorkflow), props, Guid.NewGuid()); instance.Start(); |
But, sometimes, you will be required to start a single activity. This sounds as some very simple and theoretical case, but at least when unit tests for the workflow have to be implemented, you will notice that this is not trivial as expected. Now, let's take a look how to start a single activity as UnitTest in VS:
[TestMethod] public void TestMethod00() { WorkflowRuntime runtime = new WorkflowRuntime();
ManualWorkflowSchedulerService scheduler = new ManualWorkflowSchedulerService();
runtime.AddService(scheduler);
MyActivity activity = new MyActivity (); WorkflowInstance instance; Dictionary<string, object> props = new Dictionary<string, object>();
props.Add("WorkflowArgument", "test");
instance = runtime.CreateWorkflow(activity.GetType(), props, Guid.NewGuid()); instance.Start(); scheduler.RunWorkflow(instance.InstanceId); } |
As shown in example above, one activity can be started almost in the same way as the workflow. The only difference is that you have to a care by yourself about scheduling of the activity. For this purpose the ManualWorkflowSchedulerService is used. This service ensures that the workflow is started as blocking call in the same thread as the thread which has invoked the method RunWorkflow. Such scenario can be very useful for example in one ASP.NET application.
If you have some more sophisticated tests, you might create dynamically test workflows, which host your activity. In this case we do not deal with known types as in previous two examples (known types are in this case MyWorkflow and MyActivity). Moreover, it could be useful to manipulate XOML files and then to create the activity instance by deserializing of the XOML.
Following example shows a XOML which defines a workflow with one activity:
string m_Xoml = @"<ns:MyActivity xmlns:ns=""http://daenet.eu/workflow.activities""></ns:MyActivity>"; |
To be able to deserialize this XOML, somewhere in the assembly which contains the type MyActivity following snippet has to be pasted:
[assembly: XmlnsDefinition("http://daenet.eu/workflow.activities ", "Daenet.Workflow.Activities")] |
This defines the mapping from namespace used in the code and XML namespace. After all, implement following method which does all magic. This method shows how to invoke the activity type from workflow described in pure XOML provided as string:
private Activity GetActivityTypeFromXoml(string xoml) { XmlReader reader = XmlReader.Create(new StringReader(xoml));
TypeProvider typeProvider = new TypeProvider(m_Runtime); typeProvider.AddAssembly(Assembly.Load("Assembly.Containing.MyActivity"));
ServiceContainer container = new ServiceContainer(); container.AddService(typeof(ITypeProvider), typeProvider);
DesignerSerializationManager manager = new DesignerSerializationManager(container); manager.CreateSession();
WorkflowMarkupSerializationManager serializationManager = new WorkflowMarkupSerializationManager(manager);
Activity activity = new WorkflowMarkupSerializer().Deserialize(serializationManager, reader) as Activity;
return activity; } |
To be sure that all works fine, try following code, which shows how to execute the activity created from XOML:
[TestMethod] public void TestMethod00() { Activity activity = GetActivityTypeFromXoml(m_Xoml);
WorkflowRuntime runtime = new WorkflowRuntime(); ManualWorkflowSchedulerService scheduler = new ManualWorkflowSchedulerService();
runtime.AddService(scheduler);
WorkflowInstance instance;
instance = runtime.CreateWorkflow(activity.GetType(), props, Guid.NewGuid()); instance.Start();
scheduler.RunWorkflow(instance.InstanceId); } |
There is also one more example, which has been briefly described by Scott. Scott describes in his post how to start the workflow by passing of the reader build on the top of string containing the XOML. Following code snippet shows shortly how to do that:
XmlReader reader = XmlReader.Create(new StringReader(xoml)); instance = runtime.CreateWorkflow(reader, null, props); |
Hope this helps you build better tests.
Posted
Jul 31 2007, 11:01 PM
by
Damir Dobric