如何开始使用SitecoreFakeDb进行Sitecore单元测试

时间:2016-11-25 17:28:07

标签: c# unit-testing sitecore

我试图找到正确的方法来开始对下面的代码进行单元测试:

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);
    }
}

我对单元测试很陌生,所以我选择了我能找到的最简单的实用程序来测试。这是我的单元测试的开始:

[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);
    }
}

所以我有几个问题,我先解释一下我的思考过程。 FindById目前取决于Sitecore.Context.Database哪个不适用于单元测试,因此我们使用了SitecoreFakeDb。我没有实现GetItem方法,但我的想法是我使用项目设置SitecoreFakeDb的实例,然后CUT应该能够通过id获取项目。

1)但是,为了测试这段代码,我需要能够用一个FakeDb实例替换Sitecore.Context.Database。为此,我创建了ISitecoreDatabase,然后它有GetItem()等方法及其默认(实际)Sitecore数据库将实现的所有重载以及FakeDb。对于接口有多少种方法,这不会开始失控吗?

2)当针对最终对象进行断言时,在这种情况下,我断言所返回的对象具有与我期望的Id相同的字段。这是一种有效的方法,还是将整个实际对象与预期对象进行比较的更好方法?

1 个答案:

答案 0 :(得分:0)

一个可用于单元测试的选项Sitecore将使用模拟框架,如Moq。

通过这样做,您可以明确设置每个单元测试,以仅测试适用于您需要测试的项目。这使您不必完全设置数据库,并允许您仅测试每个单元测试中应测试的内容。

以下是您可以编写测试的示例。

private Mock<IMyItemInDatabase> MyItemInDatabaseModel { get; set; };

[TestInitialize]
public void Setup()
{
    var mockSitecoreContext = new Mock<ISitecoreContext>();
    this.MyItemInDatabaseModel = new Mock<IMyItemInDatabase>();

    this.MyItemInDatabaseModel.SetupAllProperties();

    mockSitecoreContext.Setup(sc =>sc.GetItem<IMyItemInDatabase
        (It.IsAny<string>(), false, false)).
        Returns(this.MyItemInDatabaseModel.Object);
}

[TestMethod]
public void MyItemInDatabaseModel_Should_Not_Be_Null()
{
    //....perform unit test here
}