我建立一个ASP.NET应用程序MVC4。 我没有使用任何嘲弄的框架,如果可能的话,在这一点上不喜欢。 我的问题是两个部分。
我有一个使用在Global.asax中创建的变量的控制器。 在控制器我访问这样的变量。
HttpContext.Application["MyVar"]
1)这是一个最佳实践的应用程序范围变量的使用? 如果没有,什么是最好的方法是什么?
在试图单元测试该控制器添加以下代码(从这里 )到我的试验方法。
MyController target = new MyController();
var request = new HttpRequest("", "http://example.com/", "");
var response = new HttpResponse(System.IO.TextWriter.Null);
var httpContext = new HttpContextWrapper(new HttpContext(request, response));
target.ControllerContext = new ControllerContext(httpContext, new RouteData(), target);
target.ControllerContext.HttpContext.Application["MyVar"] = new MyVar();
问题是我不能给应用添加任何东西。 的最后一行代码似乎并没有做任何事情,集合保持空。 我也是在VS的立即窗口试过这种没有成功。
2)在单元测试中,我怎样才能添加应用程序级的变量控制器的需求?
一般来说全局都不好进行测试。 还有,你可能至少需要两种方法。
使用像模拟框架的Pex /痣 ,NMock等。
使用反转的控制的方法( NInject是我的最爱)。 如果像控制器类具有外部依赖性,它要求的界面,典型地在其构造。
私人只读IApplicationSettings _settings;
公共myController的(IApplicationSettings设置){_settings =设置; } }
空隙的someMethod(){_settings.Get( “MyVar的”); } }
这样,你可以写现实和测试实现。
public LiveAppSettings : IApplicationSettings
{
public string Get(string key)
{
return HttpContext.Current.Application[key];
}
}
随着Ninject,可以绑定在应用程序启动时的任何一种实现:
var kernel = new StandardKernel();
kernel.Bind<IApplicationSettings>().To<LiveAppSettings>();
这是一个最佳实践的应用程序范围变量的使用?
最好的做法是有点主观的概念,并没有完全解释您的情况,什么恰恰是你想实现我不想讨论这个问题。
我们可以不讨论这是否是最好的做法,但是从我可以看到它是没有错无论是。 这是因为你使用的是抽象,允许代码进行单元测试是没有错的。
在单元测试中,我该怎么添加应用程序级的变量控制器的需求呢?
你可以使用一个模拟框架,如犀牛嘲笑嘲笑抽象控制器的需求。 让我们以一个例子如下控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
var myVar = (MyVar)HttpContext.Application["MyVar"];
return Content(myVar.Foo);
}
}
我们希望进行单元测试索引操作。 下面是一个示例单元测试:
[TestMethod]
public void Index_Action_Should_Retrieve_MyVal_From_AppState()
{
// arrange
var target = new HomeController();
var httpContext = MockRepository.GeneratePartialMock<HttpContextBase>();
var application = MockRepository.GeneratePartialMock<HttpApplicationStateBase>();
application.Expect(x => x["MyVar"]).Return(new MyVar { Foo = "bar" });
httpContext.Expect(x => x.Application).Return(application);
target.ControllerContext = new ControllerContext(httpContext, new RouteData(), target);
// act
var actual = target.Index() as ContentResult;
// assert
Assert.AreEqual("bar", actual.Content);
}