I'm completely new in Unit testing, trying to implement Unit testing for a navigation header component using xUnit, Moq and FluentAssertions library.
Below are my code for Navigation Header implementation:
INavigationRepository
public interface INavigationRepository
{
Item GetItem(string dataSourceId);
Header GetHeader(Item item);
Footer GetFooter(Item item);
}
NavigationRepository
[Service(typeof(INavigationRepository))]
public class NavigationRepository : INavigationRepository
{
private readonly INavigationRepository m_navigationRepository;
public NavigationRepository(INavigationRepository navigationRepository)
{
m_navigationRepository = navigationRepository;
}
public Item GetItem(string dataSourceId)
{
var item = Sitecore.Context.Database.GetItem(dataSourceId);
if (item == null)
{
return null;
}
return item;
}
public Header GetHeader(Item item)
{
return CreateHeaderItem(item);
}
private List<NavigationItem> GetEvents(ReferenceField eventsRoot)
{
var Events = new List<NavigationItem>();
foreach (Item i in eventsRoot.TargetItem.Children)
{
Events.Add(GetNavigationItem(i, ItemExtensions.GetItemUrl(i)));
}
return Events;
}
private NavigationItem GetNavigationItem(Item item, string itemUrl)
{
return new NavigationItem { Item = item, ItemUrl = itemUrl };
}
private Header CreateHeaderItem(Item item)
{
ImageField logo = item.Fields[Templates.Header.Fields.Logo];
ReferenceField homelink = item.Fields[Templates.Header.Fields.HomeLink];
ReferenceField eventsRoot = item.Fields[Templates.Header.Fields.EventsRoot];
LinkField scheduleLink = item.Fields[Templates.Header.Fields.ScheduleLink];
LinkField newsLink = item.Fields[Templates.Header.Fields.NewsLink];
return new Header
{
HomelinkUrl = FieldExtensions.GetUrl(homelink),
Events = GetEvents(eventsRoot),
LogoUrl = FieldExtensions.ImageUrl(logo),
LogoAlt = FieldExtensions.ImageAlt(logo),
ScheduleLinkUrl = FieldExtensions.LinkFieldUrl(scheduleLink),
NewsLinkUrl = FieldExtensions.LinkFieldUrl(newsLink)
};
}
}
Header.cs
public class Header
{
public string LogoUrl { get; set; }
public string LogoAlt { get; set; }
public string HomelinkUrl { get; set; }
public List<NavigationItem> Events { get; set; }
public string ScheduleLinkUrl { get; set; }
public string NewsLinkUrl { get; set; }
}
NavigationItem.cs
public class NavigationItem
{
public Item Item { get; set; }
public string ItemUrl { get; set; }
}
NavigationController
public class NavigationController : Controller
{
private readonly INavigationRepository m_navigationRepository;
public NavigationController(INavigationRepository navigationRepository)
{
m_navigationRepository = navigationRepository;
}
// GET: Default
public ActionResult GetHeader()
{
Item contextItem = m_navigationRepository.GetItem(RenderingContext.CurrentOrNull.Rendering.DataSource);
var model = this.m_navigationRepository.GetHeader(contextItem);
return View(model);
}
}
Unit Test , currently I'm only testing for null item
[Fact]
public void GetHeader_ItemIsNull_ReturnsEmpty()
{
// arrange
var businessLogicFake = Substitute.For<INavigationRepository>();
var sut = new NavigationRepository(businessLogicFake);
var db = Substitute.For<Database>();
var item = CreateItem(db);
//act
var result = sut.GetHeader(item);
//assert
result.Should().BeNull();
}
private Item CreateItem(Database database)
{
var item = Substitute.For<Item>(ID.NewID, ItemData.Empty, database);
var fields = Substitute.For<FieldCollection>(item);
item.Fields.Returns(fields);
return item;
}
The tests are getting failed, what else do I need to include? Or am I implementing it in a wrong way? Please guide me with the implementation and also the best practices.
Thanks a lot for the help.
Database
orItem
- You would need to use something like FakeDB