2013-09-24 24 views

回答

4

這是一個挑戰,因爲您需要接口的具體版本才能在保存之前寫入值。簡單的解決方法是使用像NSubstitute嘲弄的框架,uisng如下界面:

[SitecoreType(TemplateId = "{7FC4F278-ADDA-4683-944C-554D0913CB33}", AutoMap = true)] 
    public interface StubInterfaceAutoMapped 
    { 
     Guid Id { get; set; } 

     Language Language { get; set; } 

     string Path { get; set; } 

     int Version { get; set; } 

     string Name { get; set; } 

     string StringField { get; set; } 
    } 

我可以創建以下測試:

[Test] 
    public void Create_UsingInterface_CreatesANewItem() 
    { 
     //Assign 
     string parentPath = "/sitecore/content/Tests/SitecoreService/Create"; 
     string childPath = "/sitecore/content/Tests/SitecoreService/Create/newChild"; 
     string fieldValue = Guid.NewGuid().ToString(); 

     var db = Sitecore.Configuration.Factory.GetDatabase("master"); 
     var context = Context.Create(Utilities.CreateStandardResolver()); 
     context.Load(new SitecoreAttributeConfigurationLoader("Glass.Mapper.Sc.Integration")); 
     var service = new SitecoreService(db); 

     using (new SecurityDisabler()) 
     { 
      var parentItem = db.GetItem(parentPath); 
      parentItem.DeleteChildren(); 
     } 

     var parent = service.GetItem<StubClass>(parentPath); 

     var child = Substitute.For<StubInterfaceAutoMapped>(); 
     child.Name = "newChild"; 
     child.StringField = fieldValue; 

     //Act 
     using (new SecurityDisabler()) 
     { 
      service.Create(parent, child); 
     } 

     //Assert 
     var newItem = db.GetItem(childPath); 

     Assert.AreEqual(fieldValue, newItem["StringField"]); 

     using (new SecurityDisabler()) 
     { 
      newItem.Delete(); 
     } 

     Assert.AreEqual(child.Name, newItem.Name); 
     Assert.AreEqual(child.Id, newItem.ID.Guid); 
    } 

這工作的,因爲Glass.Mapper解析的方式鍵入要映射:

/// <summary> 
    /// Gets the type configuration. 
    /// </summary> 
    /// <param name="obj">The obj.</param> 
    /// <returns>AbstractTypeConfiguration.</returns> 
    public AbstractTypeConfiguration GetTypeConfiguration(object obj) 
    { 
     var type = obj.GetType(); 
     var config = TypeConfigurations.ContainsKey(type) ? TypeConfigurations[type] : null; 

     if (config != null) return config; 

     //check base type encase of proxy 
     config = TypeConfigurations.ContainsKey(type.BaseType) ? TypeConfigurations[type.BaseType] : null; 

     if (config != null) return config; 

     //check interfaces encase this is an interface proxy 
     string name = type.Name; 
     //ME - I added the OrderByDescending in response to issue 53 
     // raised on the Glass.Sitecore.Mapper project. Longest name should be compared first 
     // to get the most specific interface 
     var interfaceType = type.GetInterfaces().OrderByDescending(x=>x.Name.Length).FirstOrDefault(x => name.Contains(x.Name)); 

     if (interfaceType != null) 
      config = TypeConfigurations.ContainsKey(interfaceType) ? TypeConfigurations[interfaceType] : null; 

     return config; 
    } 

注意,如果不能找到一個直接的匹配類型,將開始根據相關聯的類型過去了,接口的種類確定首先使用名稱查找基礎。現在我懷疑NSubstitute的工作原理是因爲它也使用了Castle Dynamic Proxies,用其他模擬框架測試它會很有趣。

+0

感謝您的快速響應並解釋了這是如何工作的,特別是對接口名稱長度的依賴。我不確定我喜歡在我的主線代碼中包含隔離框架,所以我可能會在創建該項目的類中或附近創建接口的實現。這感覺有點多餘,但從技術上講仍然是DRY,因爲接口是記錄的定義。 –

相關問題