Pages

Tuesday, April 19, 2011

Unit Testing with the Dynamics CRM ServiceContext

One of the nice things in Dynamics CRM 2011 and in a similar way in CRM4.0 with Sdk 13 is the ability to query CRM data using LINQ.

The centerpiece for this feature is the ServiceContext. This allows you to do a query using LINQ.

Now when it comes to unit testing the code the ServiceContext is a pain.

What I wanted to do is to be able to define the data, the ServiceContext queries on, while not being connected to CRM.

So, I needed a way to redirect the ServiceContext to a List.

Searching through documentation I found the overridable

protected IQueryable<TEntity> CreateQuery<TEntity>(IQueryProvider provider, string entityLogicalName)

method. This is a factory method that than uses the query provider to query the data.


Now I extend the ServiceContext class and override the CreateQuery method:

public class TestServiceContext : ServiceContext
{
public ICollection<Entity> Data { get; private set; }

public TestServiceContext(IOrganizationService service, ICollection<Entity> data) : base(service)
{
Data = data;
}

[SuppressMessage("Microsoft.Design", "CA1004", Justification = "Design cannot be changed, as method signature is provided by Xrm OrganizationServiceContext")]
protected override IQueryable<TEntity> CreateQuery<TEntity>(IQueryProvider provider, string entityLogicalName)
{
return Data.OfType<TEntity>().Where(data => { var entityData = data as Entity;
if (entityData != null)
return entityData.LogicalName == entityLogicalName;
else
return false;}).AsQueryable();
}
}

Basically there can be two cases that have to be reckoned with:



  • Queries created using ServiceContext.CreateQuery<Account>()
  • Queries created using ServiceContext.CreateQuery(Account.LogicalName)

That’s why we reduce the returned data set to those OfType<TEntity> and then query it down to those entities having the specified logical name.


Using this implementation of TestServiceContext now actually queries on the Data collection.


Now you should have a Factory that creates your ServiceContext in your code, using a Mocking library you can then return the TestServiceContext when calling the factory.


I will show a use case and a test in the next couple of days.

No comments:

Post a Comment