So, here I will explain and give code to show you how to do proper unit testing. I'm going under the assumption that you do know how to hook up a Workflow with WCF service. Otherwise just follow the code in the example project and you will quickly get it.
This post will show the basics first and later I will provide more posts of how to write unit test for different scenarios with ReceiveActivity and SendActivity.
First off, I created a simple project to illustrate the scenario to create a client object and post it to a service that has a workflow. The workflow is very basic that it will receive the Client object message and save it to a database. I will just fake the actually writing to the database.
The project structure:
Firstly we define the ServiceContract IClientService and hook it up to the workflow CreateClientWorkflow.xoml ReceiveActivity.
Next I created a custom WorkflowServiceHostFactory that I will explain later in another post. I removed the code behind for the ClientService.svc and made the following changes.
1: <%@ ServiceHost Service="ClientWorkflowLibrary.CreateClientWorkflow, ClientWorkflowLibrary, Version=1.0.0.0, Culture=neutral"
2: Factory="CommonLibrary.WorkflowServiceHostFactory, CommonLibrary, Version=1.0.0.0, Culture=neutral" %>
The Proper Unit Test Code
1: [TestMethod]
2: [Description("Run Unit Test with Administrator privlidges. (VS in Administrator mode)")]
3: public void CreateClientWorflow_ReceiveCreateClient_ReturnClientWidthValidGuid()
4: {
5: // Arrange
6: Client requestClient = new Client
7: {
8: Id = Guid.Empty,
9: Name = "User",
10: Surname = "Nobody"
11: };
12: Client responseClient = null;
13:
14: // Setup WCF and WF
15: Uri baseAddress = new Uri("http://127.0.0.1:8999/UnitTestHosting");
16: WorkflowServiceHost host = new WorkflowServiceHost(typeof(CreateClientWorkflow), baseAddress);
17:
18: host.AddServiceEndpoint(typeof(IClientService), new WSHttpContextBinding(), "CreateClient");
19:
20: ServiceMetadataBehavior smb = new ServiceMetadataBehavior { HttpGetEnabled = true };
21: host.Description.Behaviors.Add(smb);
22:
23: // Add Custom Services to Workflow runtime
24: WorkflowRuntimeBehavior runtime = host.Description.Behaviors.Find();
25: runtime.WorkflowRuntime.AddService(new ClientRepository());
26:
27: // To enable Workflow Tracking and Persistence
28: //string connectionString = "Data Source=(local);Initial Catalog=Workflow;Integrated Security=true";
29: //runtime.WorkflowRuntime.AddService(new SqlTrackingService(connectionString));
30: //runtime.WorkflowRuntime.AddService(new SqlWorkflowPersistenceService(connectionString));
31:
32: // Act
33: try
34: {
35: host.Open();
36: EndpointAddress address = new EndpointAddress("http://127.0.0.1:8999/UnitTestHosting/CreateClient");
37: IClientService service = ChannelFactory.CreateChannel(new WSHttpContextBinding(), address);
38:
39: responseClient = service.CreateClient(requestClient);
40:
41: host.Close();
42: }
43: catch (Exception e)
44: {
45: Assert.Fail(string.Format("Error: {0}", e));
46: }
47: finally
48: {
49: if (host.State != CommunicationState.Closed)
50: {
51: host.Abort();
52: }
53: }
54:
55: // Assert
56: Assert.IsNotNull(responseClient);
57: Assert.AreNotEqual(Guid.Empty, responseClient.Id);
58: Assert.AreEqual(requestClient.Name, responseClient.Name);
59: Assert.AreEqual(requestClient.Surname, responseClient.Surname);
60: }
Firstly you setup the Uri address of where you want to host the service that will be dynamically get set as the unit test is run. Then you create the WorkflowServiceHost and assign the workflow that you want to test. Add an Service endpoint with the ServiceContact that is used in the workflow and the appropriate binding that should be used. Finally a name for the endpoint that you will call later to test.
You can add additional behaviour metadata. When you instantiate a WorkflowServiceHost then the WorkflowRuntimeBehaviour is automatically added. In the code I do a find on the host Behaviours to return the WorkflowRuntimeBehaviour instance. This instance is required to add additional custom service. For example the ClientRepository.You will see the code comment if you would like to add Tracking and Persistence to you workflow under test.
Now for the Act part. With WorkflowServiceHost setup we can open a connection to the service. I create a channel to the ServiceContract IClientService and assign the endpoint address that should be queried.
I call the relevant method on the ServiceContract and close the host connection afterwards.
There is a catch and finally section to make sure that no exceptions was raised and that the host was properly closed.
The Assert part is at the end to separate the asserts from any communication problems. I specify multiple asserts just to show the variety of unit tests that could be written and should actually be written to different unit tests.
Hope you enjoy this post and any feedback or recommendation is welcome!
Cheerio!
Source: ClientService 1.zip