2010-03-04 145 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); 

(本例使用訂貨數量)

相關問題