[英]Unit test controller that uses application scoped variables
我正在構建一個ASP.NET MVC4應用程序。 我沒有使用任何模擬框架,並且在可能的情況下,最好不要使用。 我的問題是2個部分。
我有一個使用在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 / Moles ,NMock等的模擬框架。
使用控制反轉方法( NInject是我的最愛)。 如果像控制器這樣的類具有外部依賴關系,則通常在其構造函數中請求接口。
私有只讀IApplicationSettings _settings;
公共MyController(IApplicationSettings設置){_settings =設置; }
void 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>();
這是應用程序范圍的變量用法的最佳實踐嗎?
最佳實踐有點主觀觀念,在沒有完全解釋您的情況以及您到底想達到什么目的的情況下,我不願討論它。
我們無法討論這是否是最佳做法,但從我的角度看,這也沒有錯。 沒錯,因為您正在使用允許對代碼進行單元測試的抽象。
在單元測試中,如何添加控制器所需的應用程序級別變量?
您可以使用諸如Rhino Mocks之類的模擬框架來模擬控制器所需的抽象。 讓我們以以下控制器為例:
public class HomeController : Controller
{
public ActionResult Index()
{
var myVar = (MyVar)HttpContext.Application["MyVar"];
return Content(myVar.Foo);
}
}
我們希望對Index操作進行單元測試。 這是一個示例單元測試:
[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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.