2016-11-25 52 views
2

我试图找到正确的方法,开始单元片的下面的代码测试:如何开始使用Sitecore的单元测试与SitecoreFakeDb

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字段为我所期望的。这是一种有效的方法,还是比较整个实际对象与预期对象的更好方法?这将单元测试Sitecore的工作

+1

您不必替换数据库,因为您已经将它抽象到接口后面。您可以轻松地模拟接口以在单元测试中按预期方式进行预成型。至于界面,它不必拥有所有的过载。只需要什么。你应该只揭露什么是必要的 – Nkosi

+0

您能否提供一个简短的摘录/例子来说明您在第一个陈述中的含义? – uioporqwerty

+0

你应该在堆栈交换中作为同样的问题。 http://sitecore.stackexchange.com/ –

回答

0

一种选择将是使用mock框架,如起订量。

通过这样做,你可以明确地建立每个单元测试只测试适用于你需要测试什么项目。这使您无需完全设置数据库,并且只允许您测试每个单元测试中应该测试的内容。

这里是你如何可以写你的测试的例子。

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 
} 
相关问题