I'm trying to find the correct approach to begin unit testing the piece of code below:
public class NameUtility
{
private readonly string _folder = Settings.GetSetting("FolderId");
public ISitecoreDatabase Database {get;set;} = new SitecoreDatabase();
public virtual Path FindById(long Id)
{
var folder = Database.GetItem(new ID(_folder));
var items = folder.GetChildren().Select(child => child.GlassCast<Path>());
return paths.SingleOrDefault(path => path.PathId == Id);
}
}
I'm quite new to unit testing so I chose the simplest utility I could find in order to test. This is the start of what my unit test looks like:
[TestFixture]
public class NameUtilityTests
{
[Test]
public void FindById_WithId_ReturnsPath()
{
var nameUtility = new NameUtility();
nameUtility.Database = new FakeSitecoreDatabase();
var path = nameUtility.FindById(1);
Assert.AreEqual(1, path.PathId);
}
internal class FakeSitecoreDatabase : ISitecoreDatabase
{
public Item GetItem(ID id)
{
throw new System.NotImplementedException();
}
}
}
//Code below is from the Code Under Test assembly.
public interface ISitecoreDatabase
{
Item GetItem(ID id);
}
public class SitecoreDatabase : ISitecoreDatabase
{
private readonly Database _database;
public SitecoreDatabase()
{
_database = Sitecore.Context.Database;
}
public SitecoreDatabase(Database database)
{
_database = database;
}
public Item GetItem(ID id)
{
return _database.GetItem(id);
}
}
So I have a couple of questions and I'll explain my thought process first. FindById
currently depends on Sitecore.Context.Database
which wouldn't work for Unit Tests so we've used SitecoreFakeDb instead. I haven't implemented the GetItem method, but the idea would be that I setup an instance of SitecoreFakeDb with the item(s) and then the CUT should be able to fetch the item by id.
1) However to test this code I need to be able to substitute Sitecore.Context.Database with an instance of the FakeDb. For this, I've created ISitecoreDatabase
and then it has methods like GetItem()
and all its overloads that the default (actual) Sitecore db would implement as well as the FakeDb. Wouldn't this begin to get out of control as far as how many methods that interface would have?
2) When asserting against the final object, in this case I'm asserting that the object returned has a field with the same Id as what I expect. Is this a valid approach, or is the better approach to compare the entire actual object with an expected object?