2013-07-24 58 views
6

所以我正在使用Umbraco 6.12,并且很难测试RenderMvcController单元甚至有可能测试RenderMvcController?

我在我的Global.ascx中实现了IApplicationEventHandler,Ninject运行正常,并且按预期运行该应用程序 - 都很好。

但是,单元测试这些控制器是另一回事。我发现这一点,并增加了最新回复:

http://issues.umbraco.org/issue/U4-1717

我现在在我的设置这个可爱的黑客:

Umbraco.Web.UmbracoContext.EnsureContext(new HttpContextWrapper(new HttpContext(new HttpRequest("", "http://www.myserver.com", ""), new HttpResponse(null))), ApplicationContext.Current); 

里面有原UmbracoContext周围有不能为空,但现在抛出:

目前尚未在Umbraco.Web.PublishedCache.PublishedCachesResolver初始化。在尝试读取之前,您必须初始化Current。

公布的缓存解析器也似乎后面的内部和保护的东西要隐藏,我不能使用反射在我不能初始化任何东西进入SetProperty反射破解。

这真的令人沮丧,我爱v6,并使用uMapper是非常好的。我可以随时向控制器注入回购,服务,命令或查询,并且生活是美好的 - 我无法覆盖控制器!

任何帮助,将不胜感激。

谢谢。

回答

10

单元测试一一把umbraco RenderMvcController,你需要grab the source code from github,自己编译的解决方案,并获得Umbraco.Tests.dll,并引用它在你的测试项目。

除此之外,您需要引用与Umbraco包一起分发的SQLCE4Umbraco.dll和内部用于嘲笑的Rhino.Mocks.dll。

为了解决这个问题,我编译了Umbraco.Tests.dll,并将其与Rhino.Mocks.dll放在一起,并将其放在this zip file上。

最后,得出从BaseRoutingTest测试,覆盖DatabaseTestBehavior到 NoDatabasePerFixture,并获得UmbracoContext和HttpBaseContext通过调用GetRoutingContext方法,如下面的代码:

using System; 
using Moq; 
using NUnit.Framework; 
using System.Globalization; 
using System.Web.Mvc; 
using System.Web.Routing; 
using Umbraco.Core.Models; 
using Umbraco.Tests.TestHelpers; 
using Umbraco.Web; 
using Umbraco.Web.Models; 
using Umbraco.Web.Mvc; 

namespace UnitTests.Controllers 
{ 
    public class Entry 
    { 
     public int Id { get; set; } 
     public string Url { get; set; } 
     public string Title { get; set; } 
     public string Summary { get; set; } 
     public string Content { get; set; } 
     public string Author { get; set; } 
     public string[] Tags { get; set; } 
     public DateTime Date { get; set; } 
    } 

    public interface IBlogService 
    { 
     Entry GetBlogEntry(int id); 
    } 

    public class BlogEntryController : RenderMvcController 
    { 
     private readonly IBlogService _blogService; 

     public BlogEntryController(IBlogService blogService, UmbracoContext ctx) 
      : base(ctx) 
     { 
      _blogService = blogService; 
     } 

     public BlogEntryController(IBlogService blogService) 
      : this(blogService, UmbracoContext.Current) 
     { 
     } 

     public override ActionResult Index(RenderModel model) 
     { 
      var entry = _blogService.GetBlogEntry(model.Content.Id); 

      // Test will fail if we return CurrentTemplate(model) as is expecting 
      // the action from ControllerContext.RouteData.Values["action"] 
      return View("BlogEntry", entry); 
     } 
    } 

    [TestFixture] 
    public class RenderMvcControllerTests : BaseRoutingTest 
    { 
     protected override DatabaseBehavior DatabaseTestBehavior 
     { 
      get { return DatabaseBehavior.NoDatabasePerFixture; } 
     } 

     [Test] 
     public void CanGetIndex() 
     { 
      const int id = 1234; 
      var content = new Mock<IPublishedContent>(); 
      content.Setup(c => c.Id).Returns(id); 
      var model = new RenderModel(content.Object, CultureInfo.InvariantCulture); 
      var blogService = new Mock<IBlogService>(); 
      var entry = new Entry { Id = id }; 
      blogService.Setup(s => s.GetBlogEntry(id)).Returns(entry); 
      var controller = GetBlogEntryController(blogService.Object); 

      var result = (ViewResult)controller.Index(model); 

      blogService.Verify(s => s.GetBlogEntry(id), Times.Once()); 
      Assert.IsNotNull(result); 
      Assert.IsAssignableFrom<Entry>(result.Model); 
     } 

     private BlogEntryController GetBlogEntryController(IBlogService blogService) 
     { 
      var routingContext = GetRoutingContext("/test"); 
      var umbracoContext = routingContext.UmbracoContext; 
      var contextBase = umbracoContext.HttpContext; 
      var controller = new BlogEntryController(blogService, umbracoContext); 
      controller.ControllerContext = new ControllerContext(contextBase, new RouteData(), controller); 
      controller.Url = new UrlHelper(new RequestContext(contextBase, new RouteData()), new RouteCollection()); 
      return controller; 
     } 
    } 
} 

此代码只被测试在Umbraco 6.1.5中。

+0

谢谢,我结束了类似的。尽管这是一个很大的努力 - 希望未来能够从核心团队中获得更多的TLC。 – Jammin

+0

@JorgeLusar,我试图通过以下示例设置带有TDD的umbraco网站,但我的第一个测试总是失败。你能检查我的问题,看看你是否有同样的问题? http://stackoverflow.com/questions/22660255/umbraco-unit-tests-failing谢谢! –