Dynamics CRM 2011 Unit Test Part 10: Microsoft Fakes with workflow activity
Dynamics CRM 2011 Unit Test Part 1: Introduction and Series Contents
The complete sample code using Microsoft Fakes can be downloaded from MSDN sample gallery: Dynamics CRM unit test using Microsoft Fakes
Unit test CRM workflow activity is similar to unit test CRM plugin in terms of the interface we have to mock. There are three distinct points in any code activity unit test, first is how to correctly invoke Execute method since it is protected, second is how to pass in the InArgument parameters and the last is how to pass in required service as extensions.
1. Correctly invoke CodeActivity.Execute(CodeActivityContext executionContext)
Since CodeActivity.Execute(CodeActivityContext executionContext) is protected, the correct way to invoke is method is to construct an instance of System.Activities.WorkflowInvoker and pass in an instance of custom code workflow activity. we can call the Invoke method on the WorkflowInvoker instance to trigger the execution of CodeActivity.Execute method.
AddMemberTeamActivity target = new AddMemberTeamActivity(); var invoker = new WorkflowInvoker(target); var outputs = invoker.Invoke(inputs);
2. Correctly pass in InArgument<T> properties
the InArgument<T> properties need to be passed in as a dictionary when call WorkflowInvoker.Invoke method
var inputs = new Dictionary<string, object>
{
{ "User", new EntityReference("systemuser", expectedUserId) },
{ "Team", new EntityReference("team", expectedTeamId) }
};
var outputs = invoker.Invoke(inputs);
3. Pass in required service as extensions
required service can be added to WorkflowInvoker.Extensions property
var invoker = new WorkflowInvoker(target); invoker.Extensions.Add<ITracingService>(() => tracingService); invoker.Extensions.Add<IWorkflowContext>(() => workflowContext); invoker.Extensions.Add<IOrganizationServiceFactory>(() => factory);
Code Under Test
public sealed class AddMemberTeamActivity : CodeActivity
{
[RequiredArgument]
[Input("User to Add")]
[ReferenceTarget("systemuser")]
public InArgument<EntityReference> User { get; set; }
[RequiredArgument]
[Input("Team to Add To")]
[ReferenceTarget("team")]
public InArgument<EntityReference> Team { get; set; }
/// <summary>
/// Executes the workflow activity.
/// </summary>
/// <param name="executionContext">The execution context.</param>
protected override void Execute(CodeActivityContext executionContext)
{
// Create the tracing service
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
if (tracingService == null)
{
throw new InvalidPluginExecutionException("Failed to retrieve tracing service.");
}
tracingService.Trace("Entered AddMemberTeamActivity.Execute(), Activity Instance Id: {0}, Workflow Instance Id: {1}",
executionContext.ActivityInstanceId,
executionContext.WorkflowInstanceId);
// Create the context
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
if (context == null)
{
throw new InvalidPluginExecutionException("Failed to retrieve workflow context.");
}
tracingService.Trace("AddMemberTeamActivity.Execute(), Correlation Id: {0}, Initiating User: {1}",
context.CorrelationId,
context.InitiatingUserId);
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
try
{
EntityReference user = this.User.Get(executionContext);
EntityReference team = this.Team.Get(executionContext);
if (!IsMemberInTeam(service, team.Id, user.Id))
{
OrganizationRequest request = new AddMembersTeamRequest { MemberIds = new Guid[] { user.Id }, TeamId = team.Id };
var response = service.Execute(request) as AddMembersTeamResponse;
}
}
catch (FaultException<OrganizationServiceFault> e)
{
tracingService.Trace("Exception: {0}", e.ToString());
// Handle the exception.
throw;
}
tracingService.Trace("Exiting AddMemberTeamActivity.Execute(), Correlation Id: {0}", context.CorrelationId);
}
internal bool IsMemberInTeam(IOrganizationService service, Guid teamId, Guid memberId)
{
OrganizationServiceContext context = new OrganizationServiceContext(service);
var query = from relationship in context.CreateQuery("teammembership")
where relationship.GetAttributeValue<Guid>("teamid") == teamId
&& relationship.GetAttributeValue<Guid>("systemuserid") == memberId
select relationship;
return query.FirstOrDefault() != null;
}
}
Unit Test
[TestClass]
public class AddMemberTeamActivityTest
{
[TestMethod]
public void ExecuteTest()
{
//
// Arrange
//
Guid actualUserId = Guid.NewGuid();
Guid actualTeamId = Guid.NewGuid();
var workflowUserId = Guid.NewGuid();
var workflowCorrelationId = Guid.NewGuid();
var workflowInitiatingUserId = Guid.NewGuid();
// IOrganizationService
var service = new Microsoft.Xrm.Sdk.Fakes.StubIOrganizationService();
service.ExecuteOrganizationRequest = r =>
{
AddMembersTeamRequest request = r as AddMembersTeamRequest;
actualUserId = request.MemberIds[0];
actualTeamId = request.TeamId;
return new AddMembersTeamResponse();
};
// IWorkflowContext
var workflowContext = new Microsoft.Xrm.Sdk.Workflow.Fakes.StubIWorkflowContext();
workflowContext.UserIdGet = () =>
{
return workflowUserId;
};
workflowContext.CorrelationIdGet = () =>
{
return workflowCorrelationId;
};
workflowContext.InitiatingUserIdGet = () =>
{
return workflowInitiatingUserId;
};
// ITracingService
var tracingService = new Microsoft.Xrm.Sdk.Fakes.StubITracingService();
tracingService.TraceStringObjectArray = (f, o) =>
{
Debug.WriteLine(f, o);
};
// IOrganizationServiceFactory
var factory = new Microsoft.Xrm.Sdk.Fakes.StubIOrganizationServiceFactory();
factory.CreateOrganizationServiceNullableOfGuid = id =>
{
return service;
};
var expectedUserId = Guid.NewGuid();
var expectedTeamId = Guid.NewGuid();
AddMemberTeamActivity target = new AddMemberTeamActivity();
using (ShimsContext.Create())
{
var fakeTarget = new DynamicsCRMUnitTest.Workflow.Fakes.ShimAddMemberTeamActivity(target);
fakeTarget.IsMemberInTeamIOrganizationServiceGuidGuid = (svc, teamId, memberId) =>
{
return false;
};
var invoker = new WorkflowInvoker(target);
invoker.Extensions.Add<ITracingService>(() => tracingService);
invoker.Extensions.Add<IWorkflowContext>(() => workflowContext);
invoker.Extensions.Add<IOrganizationServiceFactory>(() => factory);
var inputs = new Dictionary<string, object>
{
{ "User", new EntityReference("systemuser", expectedUserId) },
{ "Team", new EntityReference("team", expectedTeamId) }
};
//
// Act
//
var outputs = invoker.Invoke(inputs);
}
//
// Assert
//
Assert.AreEqual(expectedUserId, actualUserId);
Assert.AreEqual(expectedTeamId, actualTeamId);
}
[TestMethod]
public void IsMemberInTeamTest()
{
//
// Arrange
//
Guid userId = Guid.NewGuid();
Guid teamId = Guid.NewGuid();
bool expected = true;
AddMemberTeamActivity target = new AddMemberTeamActivity();
// IOrganizationService
var service = new Microsoft.Xrm.Sdk.Fakes.StubIOrganizationService();
service.ExecuteOrganizationRequest = r =>
{
List<Entity> entities = new List<Entity>
{
new Entity()
};
var response = new RetrieveMultipleResponse
{
Results = new ParameterCollection
{
{ "EntityCollection", new EntityCollection(entities) }
}
};
return response;
};
//
// Act
//
var actual = target.IsMemberInTeam(service, teamId, userId);
//
// Assert
//
Assert.AreEqual(expected, actual);
}
}
This was originally posted here.

Like
Report
*This post is locked for comments