问题描述
所以我正在使用 Umbraco 6.12 并且很难测试 RenderMvcController
.
So I'm working with Umbraco 6.12 and having great difficulty been able to test a RenderMvcController
.
我已经在我的 Global.ascx
中实现了 IApplicationEventHandler
并且 Ninject 在运行应用程序时运行良好并且符合预期 - 一切都很好.
I have implemented IApplicationEventHandler
in my Global.ascx
and Ninject is working fine and as expected when running the application - all good.
但是,对这些控制器进行单元测试是另一回事.我找到了这个,并添加了最新的回复:
However, unit testing these controllers is a different matter. I found this, and have added the latest reply:
http://issues.umbraco.org/issue/U4-1717
我现在在我的设置中有这个可爱的黑客:
I now have this lovely hack in my SetUp:
Umbraco.Web.UmbracoContext.EnsureContext(new HttpContextWrapper(new HttpContext(new HttpRequest("", "http://www.myserver.com", ""), new HttpResponse(null))), ApplicationContext.Current);
绕过原来的 UmbracoContext
不能为空,但现在抛出:
Which has got around the original UmbracoContext
cannot be null, but is now throwing:
Current 尚未在 Umbraco.Web.PublishedCache.PublishedCachesResolver 上初始化.您必须在尝试读取 Current 之前对其进行初始化.
发布的缓存解析器似乎也隐藏在内部和受保护的东西后面,我不能使用反射来破解,因为我无法初始化任何东西以传递到 SetProperty
反射.
The published caches resolver also seems to be hidden behind internal and protected stuff, which I can't use reflection to hack at as I can't init anything to pass into SetProperty
reflection.
这真的很令人沮丧,我很喜欢 v6,而且使用 uMapper 非常好.我可以随意将 repo、服务、命令或查询注入到控制器中,生活很好 - 我只是无法覆盖控制器!
It's really frustrating, I'm loving v6, and using uMapper is very nice. I can inject a repo, service, command or query at will into the controllers and life is good - I just can't cover the controllers!
对此的任何帮助将不胜感激.
Any help on this would be greatly appreciated.
谢谢.
推荐答案
要对 Umbraco RenderMvcController 进行单元测试,您需要抓取源代码来自 github 的代码,自己编译解决方案,然后获取 Umbraco.Tests.dll 并在您的测试项目中引用它.
To unit test a Umbraco RenderMvcController, you need to grab the source code from github, compile the solution yourself, and get the Umbraco.Tests.dll and reference it on your test project.
除此之外,您还需要引用随 Umbraco 包分发的 SQLCE4Umbraco.dll,以及内部用于模拟的 Rhino.Mocks.dll.
In addition to that, you need to reference the SQLCE4Umbraco.dll which is distributed with the Umbraco packages, and Rhino.Mocks.dll which is internally for mocking.
为了帮助您解决这个问题,我编译了 Umbraco 6.1.5 的 Umbraco.Tests.dll 并将其与 Rhino.Mocks.dll 放在一起,并将其放在 这个压缩文件.
To help you with this, I have compiled put the Umbraco.Tests.dll for Umbraco 6.1.5 and put it together with the Rhino.Mocks.dll and put it on this zip file.
最后,从 BaseRoutingTest 派生您的测试,将 DatabaseTestBehavior 覆盖为NoDatabasePerFixture,并通过调用 GetRoutingContext 方法获取 UmbracoContext 和 HttpBaseContext,如下代码所示:
Finally, derive your test from BaseRoutingTest, override the DatabaseTestBehavior to NoDatabasePerFixture, and get the UmbracoContext and HttpBaseContext by calling the GetRoutingContext method, as in the code below:
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 中测试过.
This code has only been tested in Umbraco 6.1.5.
这篇关于甚至可能对 RenderMvcController 进行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!