2010-03-04 48 views
1

我想测试一个使用DotNetOpenAuth的AccountController,但我遇到了问题。我想测试Logon ActionResult以查看它是否返回了正确的视图。测试失败,因为领域(我认为)有一个合同,要求HttpContext.Current不为null。我想我必须以某种方式嘲笑这个请求,但我不知道我该怎么做。测试/模拟DotNetOpenAuth控制器

这是ActionResult代码。它直接来自DotNetOpenAuth示例。

[AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken] 
public ActionResult LogOn(string openid_identifier, 
          bool rememberMe, 
          string returnUrl) 
{ 
    Identifier userSuppliedIdentifier; 
    if (Identifier.TryParse(openid_identifier, out userSuppliedIdentifier)) 
    { 
     try 
     { 
      var request = this.RelyingParty 
           .CreateRequest(openid_identifier, 
              Realm.AutoDetect, 
              Url.ActionFull("LogOnReturnTo")); 

      if (!string.IsNullOrEmpty(returnUrl)) 
      { 
       request.SetUntrustedCallbackArgument("returnUrl", returnUrl); 
      } 
      return request.RedirectingResponse.AsActionResult(); 
     } 
     catch (ProtocolException ex) 
     { 
      ModelState.AddModelError("OpenID", ex.Message); 
     } 
    } 
    else 
    { 
     ModelState.AddModelError("openid_identifier", 
           "This doesn't look like a valid OpenID."); 
    } 
    return RedirectToAction("LogOn", "Account"); 
} 

由于提前,

Pickels

回答

2

如果控制器的依赖的一个要求,HttpContext.Current是可用的,你真的不能嘲笑它直接,但你可以用这种依赖性在可测试的抽象中。

如果我们假设Realm是罪魁祸首,您必须首先从中提取一个接口

public interface IRealm 
{ 
    // I don't know what the real AutoDetect property returns, 
    // so I just assume bool 
    bool AutoDetect { get; } 
} 

你显然需要一个真正的实现IRealm的:

public class RealmAdapter : IRealm 
{ 
    bool AutoDetect { get { return Realm.AutoDetect; } } 
} 

你必须将抽象IRealm注入控制器,例如使用构造函数注入

public class MyController 
{ 
    private readonly IRealm realm; 

    public MyController(IRealm realm) 
    { 
     if(realm == null) 
     { 
      throw new ArgumentNullException("realm"); 
     } 

     this.realm = realm; 
    } 
} 

您现在可以将LogOn方法的实现更改为使用this.realm,而不是直接依赖Realm类。

单元测试现在将能够提供一个模拟IRealm实例到控制器:

var realmMock = new Mock<IRealm>(); 
var sut = new MyController(realmMock.Object); 

(本例使用订货数量)