0

我想要编写单元测试现有Sitecore的项目上MVC5使用GlassMapperORMTDS 。我嘲笑了Sitecore内容树,Sitecore上下文,项目属性,字段集合和基本项目,使用Jeff Sulit的这个非常有用的博客文章。无法通过在单位Sitecore的上下文来访问Sitecore的模拟项目(MS正版正货)测试

https://oddeven.ch/blog/mocking-sitecore-using-ms-fakes/

目前已在上述职位的设置(如共享以上链接.... 请通过它去回答之前)。我已将上述设置保存在我的业务层的单独的类文件UnitTestAssist.cs中。

现在我已经写在我从我的单元测试项目创建一个假物品,然后通过Sitecore.Context,Database.GetItem调用,它返回空访问它通过UnitTestAssist类对象的对象以下基本单元测试。

namespace MySiteCoreUnitTest 
{ 
[TestClass] 
public class DataFetch 
{ 
    IDisposable _context; 
    readonly MySiteCoreUnitTest.UnitTestAssist _scFaker = new MySiteCoreUnitTest.UnitTestAssist(); 

    [TestInitialize] 
    public void Initialize() 
    { 
     _context = ShimsContext.Create(); 
     _scFaker.Initialize(); 
    } 

    [TestCleanup] 
    public void Cleanup() 
    { 
     _context.Dispose(); 
    } 

    [TestMethod] 
    public void TestingDataFetch() 
    { 
     List<ShimField> lstfields = new List<ShimField>();    

     //Arrange 

     ShimField dummyField = new ShimField() 
     { 
      IDGet =() => ID.NewID, 
      NameGet =() => "Ava_Title", 
      ValueGet =() => "This is fucking Crazy" 
     }; 

     lstfields.Add(dummyField); 

     var expectedItem = _scFaker.CreateFakeItem(_scFaker.Home, "sample item", (itemName, inputField) => { inputField = lstfields; }); 

     // Act: 
     var actualItem = Context.Database.GetItem(expectedItem.Instance.Paths.FullPath); 
     var actualItemFields = actualItem.Fields; // On Debugging i get the field i added forcefully inside **UnitTestAssist**. 

     // Assert: 
     Assert.AreEqual(expectedItem, actualItem); 

    } 

} 
} 

这里是我用来创建模拟物品的代码。

namespace MySiteCoreUnitTest 
{ 
public class UnitTestAssist 
{ 
    private readonly Language ContextLanguage = Language.Parse("en"); 

    ShimItem CreateFakeItem(ShimItem parentItem, string name, Action<ShimItem, ShimTemplateItem, List<ShimField>> onItemCreating) 
    { 
     var id = ID.NewID; 

     var item = new ShimItem() 
     { 
      // Assigning ID.NewID directly will return a new ID every time item.ID is called 
      IDGet =() => id, 
      KeyGet =() => name.ToLower(), 
      NameGet =() => name, 
      HasChildrenGet =() => false, 
      ParentGet =() => parentItem, 
      PathsGet =() => 
      { 
       var path = (parentItem != null ? parentItem.Instance.Paths.Path : "") + "/" + name; 

       return new ShimItemPath() 
       { 
        PathGet =() => path, 
        FullPathGet =() => path, 
       }; 
      }, 
      LanguageGet =() => ContextLanguage, 
      VersionsGet =() => new ShimItemVersions() { CountGet =() => { return 1; } } 
     }; 

     // Bind item to parent item 
     if (parentItem != null) 
     { 
      var children = parentItem.Instance.HasChildren ? parentItem.Instance.Children.ToList() : new List<Item>(); 
      children.Add(item); 

      parentItem.HasChildrenGet =() => true; 
      parentItem.ChildrenGet =() => new ChildList(parentItem.Instance, children); 
      parentItem.GetChildren =() => parentItem.Instance.Children; 
     } 

     // Start faking template and field collection 
     var templateItem = new ShimTemplateItem(); 
     var field = new ShimField 
     { 

     }; 
     //var fields = new List<ShimField>(); 

     List<ShimField> fields = new List<ShimField>(); 

     //Arrange 
     ShimField dummyField = new ShimField() 
     { 
      IDGet =() => ID.NewID, 
      NameGet =() => "Ava_Title", 
      ValueGet =() => "This is fucking Crazy" 
     }; 

     fields.Add(dummyField); 

     // Call action to allow extension of item, template, and field collection faking  
     onItemCreating(item, templateItem, fields); 

     item.TemplateGet =() => templateItem; 
     item.FieldsGet =() => CreateFakeFieldCollection(item, fields); 

     return item; 
    } 

    // Create a dictionary to hold the field collection per item ID 
    private Dictionary<ID, List<ShimField>> itemFields = new Dictionary<ID, List<ShimField>>(); 

    ShimFieldCollection CreateFakeFieldCollection(ShimItem item, List<ShimField> fields) 
    { 
     foreach (var field in fields) 
      field.ItemGet =() => item; 

     ShimField _newField = new ShimField(); 

     var fieldCollection = new ShimFieldCollection() 
     { 
      ItemGetString = (fieldName) => 
      { 
       _newField = fields.SingleOrDefault(n => n.Instance.Name.Equals(fieldName, StringComparison.OrdinalIgnoreCase)); 
       return fields.SingleOrDefault(n => n.Instance.Name.Equals(fieldName, StringComparison.OrdinalIgnoreCase)); 

      } 
     }; 

     Field testField = _newField; 

     if (!itemFields.ContainsKey(item.Instance.ID)) 
       itemFields.Add(item.Instance.ID, fields); 

     else 
      itemFields[item.Instance.ID] = fields; 

     fieldCollection.Bind(itemFields[item.Instance.ID]); 

     return fieldCollection; 
    } 

    void FakeSitecoreContext() 
    { 
     ShimContext.LanguageGet =() => ContextLanguage; 
     ShimContext.SiteGet =() => new ShimSiteContext() 
     { 
      ContentLanguageGet =() => ContextLanguage 
     }; 

     Func<Func<Item, bool>, Item> getItem = (predicate) => 
     { 
      Item result; 

      return TryGetItem(this.Sitecore.Instance.Children, predicate, out result) ? result : null; 
     }; 

     ShimContext.DatabaseGet =() => new ShimDatabase() 
     { 
      GetItemString = (path) => getItem(n => n.Paths.Path.Equals(path, StringComparison.OrdinalIgnoreCase)), 
      GetItemStringLanguage = (path, lang) => getItem(n => n.Paths.Path.Equals(path) && (n.Language.Equals(lang) || n.Languages != null && n.Languages.Any(l => l.Name.Equals(lang.Name)))), 
      GetItemID = (id) => getItem(n => n.ID.Equals(id)), 
      GetItemIDLanguage = (id, lang) => getItem(n => n.ID.Equals(id) && (n.Language.Equals(lang) || n.Languages != null && n.Languages.Any(l => l.Name.Equals(lang.Name)))), 
     }; 
    } 

    bool TryGetItem(ChildList children, Func<Item, bool> predicate, out Item result) 
    { 
     result = null; 

     if (children == null || !children.Any()) return false; 

     result = children.FirstOrDefault(predicate); 

     if (result != null) return true; 

     var query = children.Where(n => n.HasChildren); 

     if (!query.Any()) return false; 

     foreach (var child in query.ToArray()) 
     { 
      if (TryGetItem(child.Children, predicate, out result)) 
       return true; 
     } 

     return false; 
    } 

    void FakeBaseItem() 
    { 
     ShimBaseItem.AllInstances.ItemGetString = (baseItem, fieldName) => 
     { 
      Item result; 

      TryGetItem(Sitecore.Instance.Children, (n) => object.Equals(baseItem, n), out result); 

      if (result != null) 
      { 
       var fields = itemFields[result.ID]; 

       var field = fields.FirstOrDefault(n => n.Instance.Name.Equals(fieldName, StringComparison.OrdinalIgnoreCase)); 

       if (field != null) return field.Instance.Value; 
      } 

      return string.Empty; 
     }; 
    } 

    public ShimItem Sitecore, Content, Site, Home; 
    public void Initialize(Action<UnitTestAssist> onInitializing = null) 
    {   

     Sitecore = CreateFakeItem(null, "sitecore", (sitecore, someFieldSitecore) => 
     { 
      Content = CreateFakeItem(sitecore, "content", (content, someFieldContent) => 
      { 
       Site = CreateFakeItem(content, "site", (site, someFieldSite) => 
       { 
        Home = CreateFakeItem(site, "home", (home, someFieldHome) => 
        { 
         // Add more items if you must to mimic your Sitecore tree 
        }); 
       }); 
      }); 
     }); 

     if (onInitializing != null) 
      onInitializing(this); 

     FakeBaseItem(); 
     FakeSitecoreContext(); 
    } 

    public ShimItem CreateFakeItem(ShimItem parentItem, string name, Action<ShimItem,List<ShimField>> onItemCreating) 
    { 
     return CreateFakeItem(parentItem, name, (i, t, f) => 
     { 
      if (onItemCreating != null) 
       onItemCreating(i,f); 
     }); 
    } 
} 
} 

我已经修改了杰夫的代码能够接受List<ShimField>从单元测试的说法,但它仍然将项目字段为空。杰夫你能帮忙吗?

回答

0

很难说没有看到'UnitTestHelperClass'类的实际代码。如果你也可以分享它,也许它会很有用。

更新: 我已经重构你的代码来解决此问题:

var expectedItem = _scFaker.CreateFakeItem(_scFaker.Home, "sample item", (itemName, inputField) => { inputField.AddRange(lstfields); });

+0

喜杰夫,我加你需要回答的代码。感谢你的帮助。 –

+0

嗨,Jeff,我正在使用Sitecore 8.1.3。您是否能够使用这段代码成功创建并访问FakeFieldCollection?我必须硬编码UnitTestAssist中的shimfield列表来生成和获取fieldcollection,同时它应该在我提供来自CreateFakeItem方法重载的输入时起作用。 –

+0

嗨尼廷!我注意到你已经添加了两次ShimField:一个在你的faker类和一个在你的单元测试中。你可能想删除faker类中的那个。无论如何,当我尝试从项目中获取字段值时(例如actualItem [“Ava_Title”]),我可以检索该字段的值。你可以改变你的测试,以便这样获得字段值吗? –

相关问题