Testable code using Dynamic Data Store
There is some talk about how testing using EPiServer is a hassle. And it is for many reasons. There are exceptions though, and Dynamic Data Store is one of them. In contrast to EPiServer.DataFactory for example, which is a sealed class, both DynamicDataStoreFactory and DynamicDataStore are abstract classes. This is good news from a testing perspective since we can override their behavior. Good work team!
The example I´m gonna show is from the EPiSocial plugin I´ve been working on, which uses DDS. This is from the CommentRepository.
Setup
First some setup changes. Instead of using DynamicDataStoreFactory.Instance to get the store:
1: public DynamicDataStoreCommentRepository()
2: {
3: this.commentStore = DynamicDataStoreFactory.Instance.GetStore(typeof(PageComment));
4: }
We can instead take a dependency to the abstract class DynamicDataStoreFactory:
1: public DynamicDataStoreCommentRepository(DynamicDataStoreFactory dynamicDataStoreFactory)
2: {
3: this.commentStore = dynamicDataStoreFactory.GetStore(typeof(PageComment));
4: }
With this small change we´ll be able to test the code in the CommentRepository.
Let´s use the GetLatestComments method as the scenario for this:
1: public IEnumerable<PageComment> GetLatestComments(int count, string pageLanguage)
2: {
3: return this.commentStore.Items<PageComment>()
4: .Where(c => c.PageLanguage == pageLanguage)
5: .OrderByDescending(c => c.Created)
6: .Take(count);
7: }
Testing
To test that method we have to setup a fake data store to test against. I did this using Moq. Let´s say that we want to test that the method returns only pages in the language that we provide. It could look something like this:
1: [Test]
2: public void Given_a_store_with_comments_for_multiple_pages_when_getting_latest_comments_then_only_comments_for_provided_page_language_is_returned()
3: {
4: // Arrange
5: var pageCommentList = new List<PageComment>();
6: pageCommentList.Add(new PageComment { PageId = 1, PageLanguage = "sv" });
7: pageCommentList.Add(new PageComment { PageId = 2, PageLanguage = "en" });
8:
9: IOrderedQueryable<PageComment> queryableItemList = new EnumerableQuery<PageComment>(pageCommentList );
10: var dataStoreFactoryMock = new Mock<DynamicDataStoreFactory>();
11: var dataStoreMock = new Mock<DynamicDataStore>(null);
12:
13: dataStoreFactoryMock
14: .Setup(x => x.GetStore(typeof(PageComment)))
15: .Returns(dataStoreMock.Object);
16:
17: dataStoreMock
18: .Setup(x => x.Items<PageComment>())
19: .Returns(queryableItemList);
20:
21: var ddsCommentRepository = new DynamicDataStoreCommentRepository(dataStoreFactoryMock.Object);
22:
23: // Act
24: var latestComments = ddsCommentRepository.GetLatestComments(3, "sv");
25:
26: // Assert
27: Assert.That(latestComments, Contains.Item(pageCommentList[0]));
28: Assert.That(latestComments, !Contains.Item(pageCommentList[1]));
29: }
That´s pretty much it, not that hard really. I think this shows how easy testing can be if it is somewhat supported by the framework. Hoping for more of this in upcoming EPiServer versions.
Comments