0

I am trying to configure a Unit Test project within my Feature directory i.e.

  • Feature
    • Activity
      • ExampleProject
      • ExampleProject.UnitTest

Implementation

  • In Unit Test Project: UnitTest.cs [TestMethod]
    {
      string val1= "Search";
      string val2= "en";
      string expectedVal = "xyz"; 

      string retVal = new Test.GetItem(val1, val2);
      Assert.AreEqual(expectedVal, retVal);
    }
  • In Implementation Class
public string GetItem(str1, str2)
{
List<SearchResultItem> matches;

     --BREAKS HERE-- using (var context = ContentSearchManager.GetIndex("sitecore_web_index").CreateSearchContext()) 
      {
        var predicate = PredicateBuilder.True<SearchResultItem>();

        predicate = predicate.And(p => p.Path.StartsWith("/sitecore/system/Dictionary"));
        predicate = predicate.And(p => p.str1== str2);

        matches = context.GetQueryable<SearchResultItem>().Where(predicate).ToList();
      }
}

I believe I have all necessary dependencies referenced (Sitecore.Kernel, Sitecore.Mvc, Sitecore.ContentSearch) but I am still getting error: Could not find configuration node: contentSearch/configuration. I have local IIS instance of my Sitecore site working where GetItem(str1, str2) is being called multiple times so not sure why a Unit Test project won't run properly.

Versions

  • Sitecore 9.2
  • .NET 4.7.2

Do I still have to make changes to config to allow for Unit Test?

Any help is appreciated, thanks.

1

First of all, you are writing unit test. Unit test means that you testing some piece of code without dependencies on data. But in your case, you using Sitecore Content Search

using (var context = ContentSearchManager.GetIndex("sitecore_web_index").CreateSearchContext()) 

But unit tests are executed in separate sandbox, they don't know anything about Sitecore. It is expected that configuration for index is not found.

You need to mock context:

var searchContext = Substitute.For<IProviderSearchContext>();
var queryable = new LuceneProviderQueryableStub(enumerable);
searchContext.GetQueryable().Returns(queryable);

And stub implementation:

    public class LuceneProviderQueryableStub<TElement> : IOrderedQueryable<TElement>, IOrderedQueryable, IQueryProvider
    {
        private readonly EnumerableQuery<TElement> innerQueryable;

        public Type ElementType { get { return ((IQueryable)innerQueryable).ElementType; } }

        public Expression Expression { get { return ((IQueryable)innerQueryable).Expression; } }

        public IQueryProvider Provider { get { return this; } }

        public LuceneProviderQueryableStub(IEnumerable<TElement> enumerable)
        {
            innerQueryable = new EnumerableQuery<TElement>(enumerable);
        }

        public LuceneProviderQueryableStub(Expression expression)
        {
            innerQueryable = new EnumerableQuery<TElement>(expression);
        }

        public IQueryable CreateQuery(Expression expression)
        {
            return new LuceneProviderQueryableStub<TElement>((IEnumerable<TElement>)((IQueryProvider)innerQueryable).CreateQuery(expression));
        }

        public IQueryable<TElement1> CreateQuery<TElement1>(Expression expression)
        {
            return (IQueryable<TElement1>)new LuceneProviderQueryableStub<TElement>((IEnumerable<TElement>)((IQueryProvider)innerQueryable).CreateQuery(expression));
        }

        public object Execute(Expression expression)
        {
            throw new NotImplementedException();
        }

        public TResult Execute<TResult>(Expression expression)
        {
            var items = this.ToArray();
            object results = new SearchResults<TElement>(items.Select(s => new SearchHit<TElement>(0, s)), 0);
            return (TResult)results;
        }

        public IEnumerator<TElement> GetEnumerator()
        {
            return ((IEnumerable<TElement>)innerQueryable).GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

Also you should not call getting index directly

ContentSearchManager.GetIndex("sitecore_web_index").CreateSearchContext()

you need wrapper that will return IProviderSearchContext: real in Sitecore context, fake in unit test context.

Then your unit test could start to work. See this gist for working example.

P.S. But your unit test in meaning of unit testing doesn't have sense. Unit test should test logic(code), but not data.

| improve this answer | |
  • Thanks for the descriptive answer. I figured you cannot access Sitecore context without via Unit Test. – LinkedListT Dec 10 '19 at 14:34
  • @LinkedListT yes, if you want to test code that depends on Sitecore Context you need to mock it. – Anton Dec 10 '19 at 14:47
  • is there any method attaching Unit test project to iis sitecore instance? My goal is to have automated testing configured on azure pipelines for build processes – LinkedListT Dec 10 '19 at 15:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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