如何在SitecoreMVC中对两个不同Sitecore上下文具有紧密耦合依赖关系的方法进行单元测试



不幸的是,我不得不为遗留的Sitecore MVC代码库编写单元测试,其中调用了两个不同的SitecoreContext。我知道这属于集成测试,但我没有在这方面教育我的项目领导的选择。因此,我选择使用FakeDb来模拟Sitecore实例,并使用NSubstitute代替注入的依赖项(由于预算限制,无法使用任何Profiler API框架,如MS Fakes、TypeMock等(。我提供以下代码:

要进行单元测试的方法

public bool DubiousMethod()
{
// This HttpContext call is pain area 1. This gets resolved when i call it using ItemContextSwitcher in Unit Tests.
string currentUrl = HttpContext.Current.Request.RawUrl; 
// This Sitecore Context call to Site Name is pain area 2. This gets resolved when Unit Tests are run under SiteContextSwitcher.
string siteName = Sitecore.Context.Site.Name;
return true/False;
}

单元测试方法

[Fact]
public void DubiousMethodUT()
{
// create a fake site context            
var fakeSite = new Sitecore.FakeDb.Sites.FakeSiteContext(
new Sitecore.Collections.StringDictionary
{
{ "name", "website" }, { "database", "web" }, { "rootPath", "/sitecore/content/home" },
{ "contentStartItem", "home"}, {"hostName","https://www.myorignalsiteurl.com"}                 
});
using (new Sitecore.Sites.SiteContextSwitcher(fakeSite))
{                           
//DubiousClassObject.DubiousMethod(home) // When Debugging after uncommenting this line i get correct value in **Sitecore.Context.Site.Name**
using (Sitecore.FakeDb.Db db = new Sitecore.FakeDb.Db
{
new Sitecore.FakeDb.DbItem("home") { { "Title", "Welcome!" } ,
new Sitecore.FakeDb.DbItem("blogs") }
})
{
Sitecore.Data.Items.Item home = db.GetItem("/sitecore/content/home");
//bool abc = confBlogUT.IsBlogItem(home);
using (new ContextItemSwitcher(home))
{
string siteName = Sitecore.Context.Site.Name;
var urlOptions = new Sitecore.Links.UrlOptions();
urlOptions.AlwaysIncludeServerUrl = true;
var pageUrl = Sitecore.Links.LinkManager.GetItemUrl(Sitecore.Context.Item, urlOptions);
HttpContext.Current = new HttpContext(new HttpRequest("", pageUrl.Substring(3), ""), new HttpResponse(new StringWriter()));

Assert.False(DubiousClassObject.DubiousMethod(home); //When Debugging after commenting above DubiousMethodCall i get correct value for **HttpContext.Current.Request.RawUrl**
}
}
}
}

正如您所观察到的,当我尝试从FakSiteContext调用该方法时,我得到了Sitecore.Context.Site.Name的正确值,但是当在该方法中调用HttpContext.Current.Request.RawUrl时,我的代码会中断。当我从ContextItemSwitcher(FakeItem(上下文调用方法时,情况正好相反。到目前为止,我还没能找到一种方法来合并这两个上下文(我认为这在Sitecore中是不可能的(。有人能建议我是否在一个总体上下文中运行我的单元测试吗?在这个上下文中,我可以控制fakeSite变量和FakeItem上下文变量,并通过扩展控制任何其他Sitecore上下文调用?

如有任何帮助,我们将不胜感激。

我建议您看看Sitecore文章中的单元测试,因为它似乎正是您所需要的。

简而言之,您需要对代码进行一些调整以使其可测试:

1( 将静态的HttpContext替换为抽象的HttpContextBase(impl.HttpContextWrapper(,这样一切都可以被安排——DubiousMethod得到一个接受DubiousMethod(HttpContextBase httpContext)的重载。

2( 至于Sitecore上下文数据,它具有Sitecore.Caching.ItemsContext绑定语义(如本文所述(,因此您可以在每次测试之前/之后清理集合,以在测试之间获得某种隔离。

或者,您可以为Sitecore烘焙一个类似的包装器。上下文就像ASP.NET团队为HttpContext->HttpContextBase&implHttpContextWrapper

最新更新