2012-01-18 21 views
2

我正在實現一個使用DotNetOpenAuth CTP庫的oauth提供程序。因此,我創建了一個mvc3應用程序,該應用程序具有一個OAuth控制器,其中包含3個方法,用於授權第三方應用程序。控制器有一個IOAuthService,它封裝了庫爲完成某些任務而必須執行的所有邏輯,但是,服務方法返回保護其構造函數的DotNetOpenOAuth對象。單元測試dotnetopenauth ctp

我想測試我的OAuthController中的方法的行爲,爲此,我試圖嘲笑我的服務方法,但我還沒有能夠做到這一點。我必須告訴moq庫什麼類型的對象我期待服務方法返回,並且由於我無法訪問這些對象的構造函數,所以我無法對我的控制器方法執行測試。

控制器:

public class OAuthController : Controller 
{ 
    private readonly IOAuthService _oAuthService; 

    public OAuthController(IOAuthService oAuthService) 
    { 
     _oAuthService = oAuthService; 
    } 

    [Authorize, AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)] 
    public ActionResult Authorize() 
    { 
     ClientApplication requestingClient; 
     var request = _oAuthService.ReadAuthorizationRequest(); 
     if (request == null) 
     { 
      throw new HttpException((int)HttpStatusCode.BadRequest, "Missing authorization request."); 
     } 

     var response = _oAuthService.RequestClientAuthorization(GetIdentity().Name, out requestingClient, request); 
     if (response != null) 
     { 
      return response.AsActionResult(); 
     } 

     var model = new AuthorizeClientApplicationViewModel 
     { 
      ClientApplication = requestingClient.Name, 
      Scope = request.Scope, 
      AuthorizationRequest = request, 
     }; 

     return View(model); 
    } 

    public virtual IIdentity GetIdentity() 
    { 
     return User.Identity; 
    } 
} 

我想測試,每當第三方應用程序沒有權限,視圖會彈出用戶請求他允許授權的應用程序。 FOT這個我需要模擬:

  • _oAuthService.RequestClientAuthorization

然後我的測試方法的設置看起來像:

var oAuthService = new Mock<IOAuthService>(); 
oAuthService.Setup(a => a.RequestClientAuthorization(userName, out client, pendingRequest)).Returns(new OutgoingWebResponse()); // DotNetOpenAuth doesn't allow me to do the **new OutgoingWebResponse** 

PD:對於這個問題我只寫了一個控制器的方法,但有3個,他們有類似的情況。

回答

1

一種可能性是寫一個包裝(以同樣的方式ASP.NET MVC抽象的所有HTTP上下文具體的東西):

public abstract class OutgoingWebResponseWrapperBase 
{ 
    protected OutgoingWebResponseWrapperBase() { } 

    public abstract ActionResult AsActionResult(); 
} 

,然後有一個天真的實現:

public class OutgoingWebResponseWrapper: OutgoingWebResponseWrapperBase 
{ 
    private readonly OutgoingWebResponse _response; 
    public OutgoingWebResponseWrapper(OutgoingWebResponse response) 
    { 
     _response = response; 
    } 

    public override ActionResult AsActionResult() 
    { 
     return _response.AsActionResult(); 
    } 
} 

現在修改IOAuthService.RequestClientAuthorization方法返回OutgoingWebResponseWrapperBase而不是OutgoingWebResponse

就像這樣:

public interface IOAuthService 
{ 
    ... 
    OutgoingWebResponseWrapperBase RequestClientAuthorization(...); 
} 

顯然控制器代碼將保持絕對相同。現在你可以在你的單元測試中嘲笑RequestClientAuthorization的返回類型,因爲它是一個抽象類。您也可以模擬AsActionResult抽象方法調用以返回一些預期的模擬實例,並且您將在您的單元測試中聲明您正在測試的控制器操作返回了此預期的操作結果。

+0

好的,我可以試試! – Daniel 2012-01-18 16:55:38

1

如果構造函數是受保護的,那麼派生類型可以訪問它。你能簡單地使用Moq來創建一個OutgoingWebResponse的模擬(它會在內部使Moq從它派生出來並調用我認爲的受保護的構造函數),並從你的模擬方法實現中返回它?

事情是這樣的:

System.Net.HttpWebResponse mockResponse; // get this from somewhere 
new Moq.Mock<DotNetOpenAuth.Messaging.OutgoingWebResponse>(mockResponse, 5); 

這應該讓你小樣的OutgoingWebResponse。接下來的問題就變成了,你從哪裏獲得HttpWebResponse實例,因爲它也只有一個受保護的構造函數。您可以繼續鏈接並模擬與OutgoingWebResponse相同的內容,並查看您獲得的距離。

+0

你可以給一個參考,舉例說明如何實現該理論? – IamStalker 2012-01-18 16:42:33

+0

不,我已經嘗試過,但系統會拋出一個異常,告訴父構造必須明確定義。 – Daniel 2012-01-18 16:53:20

+0

添加了一個示例。一個人可以做到這一點,如果有一個HttpWebResponse。 – 2012-01-19 15:23:49