Sitecore unit testing with test fixtures

Unit testing logic that uses the Sitecore content API is not very easy. Alistair Deneys has written some very good articles on it here and here. The second article describes how to use mocking. I prefer that approach over testing on a running Sitecore website (integration testing), because I want my tests to be fast and I don’t like the risk of breaking my Sitecore website by messing up the database.

But mocking can be very tedious. Having to setup all the mocks for your tests can take a lot of time and that may be used as an excuse not to unit test your code at all. Setting up large test fixtures can be very time consuming as well.

Since I recently made a Sitecore DataProvider, I’ve gotten somewhat familiar with that concept. So now I created a DataProvider that works in-memory. On startup, it loads Sitecore items from sources like Sitecore packages and serialized data (should work with TDS items as well). That should make it much easier to create test fixtures with your own items and templates! After your tests have run, your changes will be lost. That way, your tests can never ‘harm’ any database.

I’ve shared the code here on GitHub (I wanted to try GitHub). Here are some steps to help you set things up:

  1. Download the project or pull it from GitHub.
  2. Make sure all the project references are working.
  3. Edit the SampleTestProject.dll.config file and change the absolute paths to correspond with the paths on your machine.
  4. Run the unit tests in SampleTestProject (they should pass).

There are three projects in the solution:

  1. FixtureDataProvider – This is the project that contains the DataProvider. If you inherit your unit testing class from SitecoreUnitTestBase, then some basic Sitecore stuff will be configured for you before the tests are executed.
  2. SampleSitecoreProject – This project contains some logic that utilizes the Sitecore content API. More specifically, it can read KML and makes Sitecore items for every Placemark (containing a description and the coordinates of the placemark):

     

     

  3. SampleTestProject – This project contains the SampleTestProject.dll.config file, which is kind of like a very minimal Web.config (without the need for an actual website to be running). The project also contains a data folder that has some serialized items and a zip package (the test fixture data). And you’ll also find some KML files to be imported. The UnitTest class contains the test of the previous code:

     

     

Some important points I want to make:

  • Events and cache are disabled by default. So if you need to test those aspects, you’ll have to do some extra work.
  • Though I attempted to emulate the SQL DataProvider as much as possible, I can not guarantee that it behaves in the exact same way at all times. Remember that unit testing can never replace integration testing and functional testing altogether.
  • I have not yet implemented support for media (I might add support for that later, and for the MongoDB DataProvider as well). – Implemented (not yet for the MongoDB DataProvider)

Happy testing! And let me know if you have any questions or ideas!

Comments (10)

  1. 10:31, 2012/06/12Pieter  / Reply

    Hi Robin,

    Again a great project and a well documented post!

    Thanks and keep on the good work!

    Cheers,
    Pieter

  2. 11:00, 2012/08/13Vangansewinkel Benjamin  / Reply

    Thank you for this module it seem really cool. I will try to use it :-)

  3. 12:13, 2013/03/06Martijn Bos  / Reply

    Hi Robin,

    I thought that I would prepare myself for your presentation next week by checking out this post. When trying to run the tests the tests that use Sitecore throw this error. System.TypeInitializationException: De type-initialisatiefunctie voor Sitecore.SecurityModel.License.LicenseManager heeft een uitzondering veroorzaakt.

    I found some post about this on google, but no solution. Is this an error you have encountered before? And if so, do you know how to solve this?

    Cheers,
    Martijn

    • 13:48, 2013/03/06Robin Hermanussen  / Reply

      @Martijn Bos
      Hi Martijn,

      This could be a problem with your Sitecore license file. Please check in the config file within your unit testing project where you’ve configured the dataFolder to be, and make sure you have a valid license file in that location.

      You can also try configuring the log4net section to get some extra logging.

      I have to say that the setup I propose in this article can be a bit painful to get working, but once it does; it’s pretty sweet ;-)

      If you have any more questions, don’t hesitate to ask. And I’ll see you next week!

      Robin

  4. 14:21, 2014/01/03Younes van Ruth  / Reply

    Hey Robin,

    I’ve tried to get your project working with Sitecore 7. I had some troubles getting the SiteContext working (using a null atm) and get the following error when I run the test:
    http://screencast.com/t/iqqt0BDbEMk

    As far as I can see Martijn had this same issue before. I have already copied a valid Sitecore license to the folder specified in the .config on the dataFolder attribute. Offcourse I double checked wheter this path is valid. Any ideas on how to proceed?

    With kind regards,
    Younes

    • 14:22, 2014/01/03Younes van Ruth  / Reply

      @Younes van Ruth
      Test Name: TestKmlImport
      Test FullName: SampleTestProject.UnitTest.TestKmlImport
      Test Source: d:\Websites\UnitTesting\Sitecore-FixtureDataProvider\SampleTestProject\UnitTest.cs : line 25
      Test Outcome: Failed
      Test Duration: 0:00:00,3682653

      Result Message:
      Test method SampleTestProject.UnitTest.TestKmlImport threw exception:
      System.TypeInitializationException: De type-initialisatiefunctie voor Sitecore.SecurityModel.License.LicenseManager heeft een uitzondering veroorzaakt. —> System.Reflection.TargetInvocationException: Het doel van een aanroep heeft een uitzondering veroorzaakt. —> System.ArgumentException: De mapnaam \data is ongeldig.
      Result StackTrace:
      bij System.IO.FileSystemWatcher.set_Path(String value)
      bij Sitecore.IO.FileWatcher.InitializeWatcher(String filter, String folder)
      bij Sitecore.IO.FileWatcher..ctor(String folder, String filter)
      bij Sitecore.SecurityModel.License.LicenseWatcher..ctor()
      bij Sitecore.Nexus.Licensing.NexusLicenseApi.Š()
      bij Sitecore.Nexus.Licensing.NexusLicenseApi..ctor()
      — End of inner exception stack trace —
      bij System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
      bij System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
      bij System.Reflection.ConstructorInfo.Invoke(Object[] parameters)
      bij Sitecore.Reflection.ReflectionUtil.CreateObject(Type type, Object[] parameters)
      bij Sitecore.Reflection.ReflectionUtil.CreateObject(String assembly, String className, Object[] parameters)
      bij Sitecore.Reflection.ReflectionUtil.CreateObject(String typeName, Object[] parameters)
      bij Sitecore.Reflection.Nexus.GetApi[T](String typeName, T& api)
      bij Sitecore.Reflection.Nexus.get_LicenseApi()
      bij Sitecore.SecurityModel.License.LicenseManager.GetSnapshotData(Guid instance)
      bij Sitecore.SecurityModel.License.LicenseManager.UpdateSnapshot()
      bij Sitecore.SecurityModel.License.LicenseManager..cctor()
      — End of inner exception stack trace —
      bij Sitecore.SecurityModel.License.LicenseManager.DemandRuntime(Boolean acceptExpress)
      bij Sitecore.Data.Managers.ItemManager.get_Provider()
      bij Sitecore.Data.Managers.ItemManager.GetItem(ID itemId, Language language, Version version, Database database)
      bij Sitecore.Data.Database.GetItem(ID itemId)
      bij SampleSitecoreProject.SampleSitecoreLogic.ImportKml(XDocument kmlDocument, DateTime timeStamp) in d:\Websites\UnitTesting\Sitecore-FixtureDataProvider\SampleSitecoreProject\SampleSitecoreLogic.cs:regel 28
      bij SampleSitecoreProject.SampleSitecoreLogic.ImportKml(String kmlFilePath, DateTime timeStamp) in d:\Websites\UnitTesting\Sitecore-FixtureDataProvider\SampleSitecoreProject\SampleSitecoreLogic.cs:regel 18
      bij SampleTestProject.UnitTest.TestKmlImport() in d:\Websites\UnitTesting\Sitecore-FixtureDataProvider\SampleTestProject\UnitTest.cs:regel 28

  5. 20:38, 2014/01/03Robin Hermanussen  / Reply

    Hi Younes,

    I’m not sure what’s wrong exactly, but perhaps you can check if the configured paths in your config are full paths on the filesystem (this seems to help sometimes).

    I’m a bit busy at the moment, but I’ll try and get the DataProvider working with Sitecore 7 when I get the time. I’ll get back to you then.

    Robin

  6. 08:57, 2014/01/06Younes van Ruth  / Reply

    Hey Robin,

    Thanks for your quick answer. I had already double double checked the different paths in the .config. If you can make your DataProvider work with Sitecore 7 that would be great!

    Kind regards,
    Younes

    • 10:12, 2014/01/06Robin Hermanussen  / Reply

      Hi Younes,

      I’ll get back to you if/when I can make it work. I’m sorry I can’t commit to it more than that at this moment.

      Robin

  7. 13:50, 2014/01/07Jeroen Speldekamp  / Reply

    Hi

    I had the same problem and when debugging i can with the following solution that works with me.

    in the config file between the tags put in de settings below

    Put in your absolute path to the datafolder.

    This did the trick for me hope it will do so for you. And im am running on Sitecore 7

Leave a Reply

Allowed Tags - You may use these HTML tags and attributes in your comment.

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Pingbacks (0)

› No pingbacks yet.

UA-4216957-1