Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
413 views
in Technique[技术] by (71.8m points)

c# - Moq: unit testing a method relying on HttpContext

Consider a method in a .NET assembly:

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;      
}

I'd like to call this method from a unit test using the Moq framework. This assembly is part of a webforms solution. The unit test looks like this, but I am missing the Moq code.

//arrange 
 string ADAccount = "BUGSBUNNY";
 string fullADName = "LOONEYTUNESBUGSBUNNY"; 

 //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.");

Question:

  • How can I use Moq to arrange a fake HttpContext object with some value like 'MyDomainMyUser'?
  • How do I associate that fake with my call into my static method at MyIdentityBL.GetSecurityContextUserName()?
  • Do you have any suggestions on how to improve this code/architecture?
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Webforms is notoriously untestable for this exact reason - a lot of code can rely on static classes in the asp.net pipeline.

In order to test this with Moq, you need to refactor your GetSecurityContextUserName() method to use dependency injection with an HttpContextBase object.

HttpContextWrapper resides in System.Web.Abstractions, which ships with .Net 3.5. It is a wrapper for the HttpContext class, and extends HttpContextBase, and you can construct an HttpContextWrapper just like this:

var wrapper = new HttpContextWrapper(HttpContext.Current);

Even better, you can mock an HttpContextBase and set up your expectations on it using Moq. Including the logged in user, etc.

var mockContext = new Mock<HttpContextBase>();

With this in place, you can call GetSecurityContextUserName(mockContext.Object), and your application is much less coupled to the static WebForms HttpContext. If you're going to be doing a lot of tests that rely on a mocked context, I highly suggest taking a look at Scott Hanselman's MvcMockHelpers class, which has a version for use with Moq. It conveniently handles a lot of the setup necessary. And despite the name, you don't need to be doing it with MVC - I use it successfully with webforms apps when I can refactor them to use HttpContextBase.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...