2013-12-09 36 views
9

如何在ASP MVC 5(Microsoft.AspNet.Identity)中爲一個單元存根User.Identity.GetUserId()測試一個MVC5控制器? GetUserId()是一個擴展,所以我不能直接嘲笑它。我需要在測試前分配ID。 看來你必須創建一個聲明並將其分配給一個GenericIdentity。但是對於單元測試來說,這似乎很重要。你知道任何替代品嗎?如何在ASP MVC 5(Microsoft.AspNet.Identity)中存根User.Identity.GetUserId()

+0

在這裏看到我的答案:http:// stackoverflow。COM/A /2672291分之39898952 – Haohmaru

回答

12

非常感謝你這個想法很多。我正在使用NSubstitute。我既沒有Microsoft Fakes也沒有JustMock。所以我最終餡索賠直接向GenericIdentity,所以我可以控制用戶ID的價值:

string username = "username"; 
string userid = Guid.NewGuid().ToString("N"); //could be a constant 

List<Claim> claims = new List<Claim>{ 
    new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", username), 
    new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", userid) 
}; 
var genericIdentity = new GenericIdentity(""); 
genericIdentity.AddClaims(claims); 
var genericPrincipal = new GenericPrincipal(genericIdentity, new string[] { "Asegurado" }); 
controllerContext.HttpContext.User = genericPrincipal; 
+0

能否請您分享工作樣例爲每個人的利益。我也在同一條線上工作。 –

+0

IsAuthenticated仍然是錯誤的,對此的任何修復? – CularBytes

4

準備好了一些痛苦?

這將取決於你正在使用哪個模擬框架。根據我的假設,你正在使用Moq,那麼你有點失敗,因爲Moq沒有做到這一點很好。原因是Moq不能模擬擴展方法(其實它不是can,但你不/不應該這樣做:-))

如果你使用另一個模擬框架,如JustMock那麼你的里程可能會變化。據this,這是一個該死的視線比後面更容易。

我發現的最簡單的方法(這仍然是易遠)是使用Microsoft Fakes

大多數的新身份的東西是使用擴展接口編寫的。我不能爲了我的生活找出他們爲什麼認爲這將是一個好主意,但在那裏。

下面是你需要做什麼。

首先爲Microsoft.AspNet.Identity創建假裝配。您可以通過右鍵單擊組件並選擇「添加僞裝拼裝」來完成此操作。這基本上走的程序集,並創建墊片和存根,爲它找到的所有東西。你想要做的就是將電話撥到GetUserId,..實際上這並不難。

然後,你必須做你經常嘲弄的ControllerContext,聽起來很熟悉。

下面的代碼會做你要找什麼,因爲我認爲 -

 using (var context = ShimsContext.Create()) 
     { 
      Microsoft.AspNet.Identity.Fakes 
       .ShimIdentityExtensions.GetUserIdIIdentity = 
      (i) => "Mr. T"; 

      var fakeHttpContext = new Mock<HttpContextBase>(); 
      var fakeIdentity = new GenericIdentity("User"); 
      var principal = new GenericPrincipal(fakeIdentity, null); 

      fakeHttpContext.Setup(t => t.User).Returns(principal); 

      var controllerContext = new Mock<ControllerContext>(); 
      controllerContext.Setup(t => t.HttpContext) 
       .Returns(fakeHttpContext.Object); 

      var sut = new HomeController(); 
      sut.ControllerContext = controllerContext.Object; 

      var result = sut.YourTestAction(); 
      Assert.True(result.WhatYouCareAbout); 
     } 

當然,它並沒有被T.先生

HTH

0

您可以創建從MvcContrib.TestHelper.Fakes對象繼承假本金和/或身份

然後,你可以做這樣的事情:

 using (var userManager = _userManagerFactory.CreateUserManager()) 
     { 
      var userId = Guid.NewGuid().ToString(); 
      var result = userManager.CreateAsync(new IdentityUser() { Id = userId, UserName = "userName" }, "password").Result; 

      Assert.IsTrue(result.Succeeded, "failed to create user through usermanager"); 

      var fakePrincipal = new FakePrincipal(new FakeClaimIdentity(userId, "userName"), new[] { "SomeRole" }); 

      Assert.IsTrue(fakePrincipal.Identity.IsAuthenticated, "fake user did not come back authenticated"); 

     } 

我用來製造假聲明身份類是這樣的:

using System.Collections.Generic; 
using System.Security.Claims; 
using MvcContrib.TestHelper.Fakes; 

namespace Tests.Unit.Fakes 
{ 
    public class FakeClaimIdentity : ClaimsIdentity 
    { 

     private readonly FakeIdentity _fakeIdentity; 


     public FakeClaimIdentity(string id, string userName) : base(userName) 
     { 
      _fakeIdentity = new FakeIdentity(userName); 
      base.AddClaims(new List<Claim> 
      { 
       new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", userName), 
       new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", id) 
      }); 
     } 

     public override bool IsAuthenticated 
     { 
      get { return _fakeIdentity.IsAuthenticated; } 
     } 

     public override string Name 
     { 
      get { return _fakeIdentity.Name; } 
     } 

     public override string AuthenticationType 
     { 
      get 
      { 
       return _fakeIdentity.AuthenticationType; 
      } 
     } 
    } 
} 

這種方式IsAuthenticated部分也可以測試(如果你關心身份的有效性)。