Moq:单元测试依赖于HttpContext的方法

p.c*_*ell 38 c# unit-testing moq mocking

考虑.NET程序集中的方法:

public static string GetSecurityContextUserName()
{             
 //extract the username from request              
 string sUser = HttpContext.Current.User.Identity.Name;
 //everything after the domain     
 sUser = sUser.Substring(sUser.IndexOf("\\") + 1).ToLower();

 return sUser;      
}
Run Code Online (Sandbox Code Playgroud)

我想使用Moq框架从单元测试中调用此方法.该程序集是webforms解决方案的一部分.单元测试看起来像这样,但我错过了Moq代码.

//arrange 
 string ADAccount = "BUGSBUNNY";
 string fullADName = "LOONEYTUNES\BUGSBUNNY"; 

 //act    
 //need to mock up the HttpContext here somehow -- using Moq.
 string foundUserName = MyIdentityBL.GetSecurityContextUserName();

 //assert
 Assert.AreEqual(foundUserName, ADAccount, true, "Should have been the same User Identity.");
Run Code Online (Sandbox Code Playgroud)

问题:

  • 我如何使用Moq来安排假的HttpContext对象,其值如'MyDomain\MyUser'?
  • 如何将我的调用与我的调用关联到静态方法中MyIdentityBL.GetSecurityContextUserName()
  • 您对如何改进此代码/架构有任何建议吗?

wom*_*omp 43

出于这个原因,Webforms众所周知是不可测试的 - 很多代码都可以依赖asp.net管道中的静态类.

为了使用Moq测试它,您需要重构您的GetSecurityContextUserName()方法以使用HttpContextBase对象的依赖注入.

HttpContextWrapper驻留在System.Web.Abstractions.Net 3.5中.它是HttpContext类的包装器HttpContextBase,并且可以扩展,你可以HttpContextWrapper像这样构造一个:

var wrapper = new HttpContextWrapper(HttpContext.Current);
Run Code Online (Sandbox Code Playgroud)

更好的是,您可以使用Moq模拟HttpContextBase并设置它的期望.包括登录用户等

var mockContext = new Mock<HttpContextBase>();
Run Code Online (Sandbox Code Playgroud)

有了这个,您就可以调用GetSecurityContextUserName(mockContext.Object),并且您的应用程序与静态WebForms HttpContext的联系更少.如果您要进行大量依赖于模拟上下文的测试,我强烈建议您查看Scott Hanselman的MvcMockHelpers类,该类具有与Moq一起使用的版本.它可以方便地处理许多必要的设置.尽管有这个名字,你不需要使用MVC - 我可以使用webforms应用程序成功地使用它来重构它们HttpContextBase.