Home » MS CRM4 | MS CRM | C# | programming | Software Developement

How to unit test Microsoft xRM Wrapper code

17. September 2010 by Dave Hawes 0 Comments

Now this might seem like something that would be easy to do but I’ve just spent 2 days struggling to do just this because of what I consider a bug in one of the SDK wrappers. I have now found a work around to enable unit testing which I will share with you now.

The Error message

Test method XrmEntityWrappers.Tests.CaseEntity.GetCaseByTicketNumber threw exception:  System.TypeInitializationException: The type initializer for 'Microsoft.Xrm.Client.Caching.Cache' threw an exception. --->  System.IO.DirectoryNotFoundException: Could not find a part of the path 'appDomain=UnitTestAdapterDomain_ForC:\Projects\Thg.Ohov.Crm\SourceCode\Thg.Ohov.Crm\TestResults\dh27_WIN-51UPWVCUQ6V 2010-09-16 18_21_40\Out\XrmEntityWrappers.Tests.dll:key=Microsoft.Xrm.Client.Caching.InMemoryCacheProvider'..

System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
b__0(Object userData)
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
System.Threading.Mutex..ctor(Boolean initiallyOwned, String name, Boolean& createdNew, MutexSecurity mutexSecurity)
System.Threading.Mutex..ctor(Boolean initiallyOwned, String name)
Microsoft.Xrm.Client.Threading.MutexExtensions.Lock(String key, Int32 millisecondsTimeout, Action`1 action)
Microsoft.Xrm.Client.Threading.MutexExtensions.Get[T](String key, Int32 millisecondsTimeout, Func`2 loadFromCache, Func`2 loadFromService)
Microsoft.Xrm.Client.Threading.MutexExtensions.Get[T](String key, Int32 millisecondsTimeout, Func`2 loadFromCache, Func`2 loadFromService, Action`2 addToCache)
Microsoft.Xrm.Client.Threading.MutexExtensions.Get[T](String key, Func`2 loadFromCache, Func`2 loadFromService, Action`2 addToCache)
Microsoft.Xrm.Client.Caching.InMemoryCacheProvider.GetExtendedCache()
Microsoft.Xrm.Client.Caching.CacheManager.GetExtendedCache()
Microsoft.Xrm.Client.Caching.Cache..cctor()
Microsoft.Xrm.Client.Caching.Cache.Get[T](String label, Func`2 load)
Microsoft.Xrm.Client.CrmConnection..ctor(String connectionStringName, String connectionString)
Microsoft.Xrm.Client.CrmConnection.Parse(String connectionString)
Thg.Ohov.Crm.Core.XrmEntityWrappers.XrmAdapter..ctor() in C:\Projects\Thg.Ohov.Crm\SourceCode\Thg.Ohov.Crm\Core\XrmEntityWrappers\XrmAdapter.cs: line 28
Thg.Ohov.Crm.Core.XrmEntityWrappers.incident.get_XrmAdapter() in C:\Projects\Thg.Ohov.Crm\SourceCode\Thg.Ohov.Crm\Core\XrmEntityWrappers\incident.cs: line 25
Thg.Ohov.Crm.Core.XrmEntityWrappers.incident.GetIncident(String caseId) in C:\Projects\Thg.Ohov.Crm\SourceCode\Thg.Ohov.Crm\Core\XrmEntityWrappers\incident.cs: line 44
XrmEntityWrappers.Tests.CaseEntity.GetCaseByTicketNumber() in C:\Projects\Thg.Ohov.Crm\SourceCode\Thg.Ohov.Crm\XrmEntityWrappers.Tests\CaseEntity.cs: line 23

The reason for the error

The Microsoft.Xrm.Client.dll tries to create a Mutex object with the

Thread.GetDomain().FriendlyName;

When running ordinary in a console app or web app this is not a problem as the FriendlyName does not contain any ‘\’ characters. However UnitTest frameworks do put ‘\’ characters in the GetDomain().FriendlyName which then causes the Mutex object to throw a ‘System.IO.DirectoryNotFoundException’.

The fix

The real fix is for Microsoft to update the Microsoft.Xrm.Client.dll so that it doesn’t put any ‘\’ characters into the Mutex constructor. However my work around for this is thanks to Nick Watkins who found this article on how to change the GetDomain().FriendlyName

http://www.timvasil.com/blog14/post/2008/11/Fixing-Instance-names-used-for-writing-to-custom-counters-must-be-127-characters-or-less.aspx

The key bit of code being this if you want to set the FriendlyName to ‘Test’ (which doesn’t have any ‘\’ characters!):

typeof(AppDomain).GetMethod("nSetupFriendlyName", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(AppDomain.CurrentDomain, new object[] { "Test" });

To rename the GetDomain().FriendlyName before calling any of the wrapper code in the unit tests. So the test might look a bit like this:

[TestMethod()]
        public void GetIncidentTest()
        {

typeof(AppDomain).GetMethod("nSetupFriendlyName", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(AppDomain.CurrentDomain, new object[] { "Test" });

            string caseId = "1234"; // TODO: Initialize to an appropriate value
            incident expected = null; // TODO: Initialize to an appropriate value
            incident actual;
            actual = incident.GetIncident(caseId);
            Assert.AreEqual(expected, actual);

}

Summary

I’m happy now I can unit test my custom code that uses the xRM Wrappers and I hope that my support call with Microsoft will result in the SDK dll being updated.

Comments are closed