Mark Stott
May 26, 2022
(1 votes)

Unit Testing with Dynamic Data Store in CMS 12 - Part 1


If you've never heard of it, the Dynamic Data Store (DDS) which is a component that offers an API and infrastructure for CRUD operations of custom data objects.  It allows developers to access and store data without needing to provision custom tables or databases using either classes or property bags which are stored within shared tables contained in the CMS database.

Optimizely also use the same functionality for some of their own features.  For example, Optimizely Search & Navigation comes with a feature known as Best Bets which allows content editors to provide search suggestions for given search terms.  Each Best Bet has it's own entry inside of the Dynamic Data Store.

This article is the first of two articles showing developers how they can unit test with the Dynamic Data Store, each with it's own separate technical approach.  Both approaches are valid, but the choice in approach may come down to how many different operations you are under taking with the Dynamic Data Store.  Part 1 deals with the direct mocking of the Dynamic Data Store objects while Part 2 deals with abstraction of the Dynamic Data Store behind multiple interfaces.

The Repository Under Test

Lets assume we have a custom data object that we want to store in the Dynamic Data Store as follows:

public class MyCustomDataObject : IDynamicData
   public Identity Id { get; set; }
   public string UniqueText { get; set; }
   public string SomeOtherText { get; set; }

The object MyCustomDataObject has an Identity property in order to meet the IDynamicData interface which is the minimum requirement for storage within the Dynamic Data Store.  The UniqueText property should be unique to that instance of the MyCustomDataObject, the SomeOtherText is just additional information to be stored with that record.

A repository that handles the saving of MyCustomDataObject records may look something like this:

public class MyCustomDataObjectRepository
   private readonly DynamicDataStore _dataStore;

   public MyCustomDataObjectRepository(DynamicDataStoreFactory dataStoreFactory)
       _dataStore = dataStoreFactory.CreateStore(typeof(MyCustomDataObject));

   public void Save(Guid id, string uniqueText, string someOtherText)
       var matchingRecord = _dataStore.Find<MyCustomDataObject>(nameof(MyCustomDataObject.UniqueText), uniqueText).FirstOrDefault();

       if (matchingRecord != null && !matchingRecord.Id.ExternalId.Equals(id))
           throw new EntityExistsException($"An entry already exists for the unique value of '{uniqueText}'.");

       var recordToSave = Guid.Empty.Equals(id) ? CreateNewRecord() : _dataStore.Load<MyCustomDataObject>(Identity.NewIdentity(id));
       recordToSave.UniqueText = uniqueText;
       recordToSave.SomeOtherText = someOtherText;

   private static MyCustomDataObject CreateNewRecord()
       return new MyCustomDataObject { Id = Identity.NewIdentity() };

Unit Testing

In order to unit test the repository behaviour, we need to mock the Dynamic Data Store.  Optimizely does not provide any interfaces to assist with the writing of unit tests and we have to mock implementations instead. 

The mocking of implementations can come with it's own complications.  With a mock behaviour of 'strict', the mocked object will behave like the true implementation and will throw exceptions as expected.  With a mock behaviour of 'loose', no exceptions will be thrown and default values will be returned as necessary.  The default mock behavior of any mocked object is actually the strict behaviour.

The strict mock behavior makes unit testing of the Dynamic Data Store impossible with exceptions being thrown during the set up of the test.  So in the following setup method, I have mocked the StoreDefinition, the DynamicDataStore and the DynamicDataStoreFactory with a loose mock behavior.  This is done by supplying the behavior in the mock constructor. The additional parameters applied to the mock constructors are default types which fulfil the constructor of the implementation being mocked.

public class MyCustomDataObjectRepositoryTests
   private Mock<DynamicDataStoreFactory> _mockDynamicDataStoreFactory;

    private Mock<DynamicDataStore> _mockDynamicDataStore;

    private Mock<StoreDefinition> _mockStoreDefinition;

    private MyCustomDataObjectRepository _repository;

   public void SetUp()
       _mockStoreDefinition = new Mock<StoreDefinition>(
           new List<PropertyMap>(0),

        _mockDynamicDataStore = new Mock<DynamicDataStore>(

       _mockDynamicDataStoreFactory = new Mock<DynamicDataStoreFactory>();
       _mockDynamicDataStoreFactory.Setup(x => x.CreateStore(typeof(MyCustomDataObject)))

        _repository = new MyCustomDataObjectRepository(_mockDynamicDataStoreFactory.Object);

At this point we are now free to write unit tests as easily as we would do when mocking interfaces.  In the following test example, an existing record is created and is set to be the result of the mocked Find method against the DynamicDataStore. When we try to save a record with a matching uniqueText, the desired outcome is that an EntityExistsException is thrown and our assertion is constructed to prove that.

public void GivenUniqueTextExistsAgainstAnotherEntity_ThenAnEntityExistsExceptionShouldBeThrown()
   // Arrange
   var uniqueText = "i-am-unique";
   var someOtherText = "some-other-text";

   var existingRecord = new MyCustomDataObject
       Id = Guid.NewGuid(),
       UniqueText = uniqueText,
       SomeOtherText = "original-other-text"

    _mockDynamicDataStore.Setup(x => x.Find<MyCustomDataObject>(It.IsAny<string>(), It.IsAny<object>()))
                           .Returns(new List<MyCustomDataObject> { existingRecord });

    // Assert
   Assert.Throws<EntityExistsException>(() => _repository.Save(Guid.Empty, uniqueText, someOtherText));


In order to unit test against the Dynamic Data Store, you must do the following in order to write unit tests as normal:

  • Mock the StoreDefinition with MockBehavior.Loose.
  • Mock the DynamicDataStore with MockBehavior.Loose and pass in the mock of the StoreDefinition.
  • Mock the DynamicDataStoreFactory with either mock behavior and set up the CreateStore method to return the mocked DynamicDataStore.

To be continued in Part 2...

May 26, 2022


Please login to comment.
Latest blogs
The 1001st Piece in your 1000 Piece Puzzle: .NET Default Interface Functions

I was recently working with a client who wanted a reasonably large subsystem added to Optimizely that would add automated management to their...

Greg J | Nov 28, 2022 | Syndicated blog

Video Demonstration, creating a CMS12 Alloy Sample Site

Hey All Below you will find a quick video demonstration on how to install a local version of Alloy Sample based on CMS12 / .Net 6. As you will see ...

Minesh Shah (Netcel) | Nov 28, 2022

How to create an admin user I Optimizely CMS – with Episerver CLI

In this blog post I’ll show how to create an admin user for Optimizely CMS in a new environment where you don’t have access to the admin interface.

Ove Lartelius | Nov 28, 2022 | Syndicated blog

Optimizely shortcuts in CMS 12 will get a trailing slash appended!

Not all URLs will work when the trailing slash is added, and that could cause problems. Hopefully it will be fixed soon.

Tomas Hensrud Gulla | Nov 26, 2022 | Syndicated blog

One week left of the beta certification period

Today it's one week until the last beta certification day. Do you exam no later than Wednesday the 30th.  Here are the reference and exam guides:...

Karen McDougall | Nov 23, 2022

Unbelievable FREE Heatmapping With Optimizely Web

Within this guide, you will learn how to integrate a free heat mapping tool to Optimizely Web so you can turbocharge your A/B testing capabilities....

Jon Jones | Nov 22, 2022 | Syndicated blog