0

Have anyone used Mock Test framework for unit testing? I need to perform an unit testing for parent child functionality and am not able to get it resolved, because i am not getting a parent child relationships using Mock setup. Please help me on the same. I need to mock an entire hierarchy level of parent and children

I have an article category section, which has different articles in it. I need to get all the articles, with the category name and the code logic is working fine. But I need to create a mock parent child relation setup for the same so that i can unit test that too.

Please help on this

1

2 Answers 2

1

Using Sitecore.FakeDb you can create something like this:

    public void YourTest()
    {
        using (var db = GetHierarchyItems())
        {
           <.. run your testing here..>
        }
    }

    private static Db GetFullBreadcrumbsItems()
    {
        return new Db
        {
            new DbItem("Parent", ID.NewID, IConstants.WhateverTemplateId)
            {
                new DbItem("Child", ID.NewID, IConstants.WhateverTemplateId)
                {
                    new DbItem("Grandchild", ID.NewID, IConstants.WhateverTemplateId)
                },
                new DbField("Some Field Of Parent Item", IConstants.SomeFieldId)
                {
                     Value = "something"
                },
            }
        };
    }
1
1

Ultimately it depends on what type of item/class you are passing into your code or logic in order to make it truly "testable" and what that parent child relationship really is.

Sitecore.FakeDb is a great tool for faking Sitecore data where you are simply not able to avoid proper Sitecore Items. When you can avoid using Sitecore Items in your code, when they translate to more generic classes like POCOs or DTOs, you can use mocking frameworks like Moq (but there are literally hundreds of mocking frameworks out there). I had wrote a post a while back covering unit testing and mocking:

The below snippet is an example when you can try and avoid using Items (illustrated using a test around search):

[Test]
[Category("UnitTest")]
public void ExecuteSearchQuery()
{
    //the search context most often will just be the sitecore search context 
    //but could be outside of sitecore
    var mockSearchProvider = new Mock<IProviderSearchContext>();

    //the search repository consumes the provider which most often 
    //will be sitecore but could be another provider and another mechanism 
    var mockSearchRepository = new Mock<ISearchRepository>();

    //the search service instance we want to mock
    var searchService = new SearchService(mockSearchProvider.Object, 
                                               mockSearchRepository.Object);

    //mock the repository
    var mockResultsList = new List<SearchHit<SearchResult>>();
    mockResultsList.Add(new SearchHit<SearchResult>(1, new SearchResult()
    {
        Content = "test",
        CreatedBy = "admin",
        CreatedDate = DateTime.MinValue,
        DatabaseName = "web",
        Datasource = null,
        ExcludeFromSearch = false,
        FullLinkToItem = "http://linktoitem",
        IsPage = true
    }));

        var mockSearchResults = new SearchResults<SearchResult>(mockResultsList, 1);

    mockSearchRepository
        .Setup(ss => ss.Search(mockSearchProvider.Object, 
                                        It.IsAny<string>(), 
                                        It.IsAny<int>(), 
                                        It.IsAny<int>()))
        .Returns(mockSearchResults);

    //test the rest of the search using the mocked provider
    var searchResultsDto = searchService.SiteSearch("test", 1, 10);

    //assert
    searchResultsDto.Hits.Count().Should().Be(1);
} 

To summarize the above, the mockSearchProvider and mockSearchRepository are proper Sitecore interfaces that have been mocked, the searchService is the logic we are covering in the test, and the mockResultsList is a generic List<> of items that will be used to drive what would normally be the results from something like the Content Search API.

If you simply can't avoid a direct reference to a Sitecore Item, you can mock using Sitecore.FakeDb like @ellele's answer above:

[Test]
[Category("UnitTest")]
public void TestYourClassLogic()
{
    //setup
    var testArticle1 = new DbItem("testArticle1", ID.NewID, IArticleConstant.TemplateId);
    var testArticle2 = new DbItem("testArticle1", ID.NewID, IArticleConstant.TemplateId);
    var parent = new DbItem("testArticleSection") { testArticle1, testArticle2 };
    var _db = new Db(){parent};

    //test the innerds of the YourClass (the class you have your logic in) that actually calls .GetItem...
    var _mockSitecoreContext = new Mock<ISitecoreContext>();
    _mockSitecoreContext.Setup(sc => sc.Database).Returns(_db.Database);
    var yourClass = new YourClass(_mockSitecoreContext.Object);
    var result = tagHelper.YourLogicDoSomethingOnThisArticle(testArticle1.ID);

    result.Should().Be("ExpectedValue");

    //teardown
    _db.Dispose();
}

Why did I cover search in this post when that's not the OP's question/situation? It's the thing I see in most sites, with the most complexity and the easiest to relate to. My end goal is to just show that if you can avoid depending on the Item directly, mocking and unit testing will almost always be easier (but not always unavoidable). The second thing I wanted to illustrate is that in order to really prove things to be "testable" you need to mock Sitecore layers/services/APIs and likely refactor your own code in order to make it testable. Unit testing done right is not an easy checkbox to fill.

I really hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.