2016-11-25 78 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 
} 
相關問題