2016-07-12 25 views
10

Tôi đang cố gắng kiểm tra đơn vị mã điều khiển của mình để nhận thông tin từ ClaimsPrincipal.Current. Trong các mã điều khiển tôiCách thêm xác nhận quyền sở hữu vào xác nhận quyền sở hữu giả mạo

public class HomeController { 
    public ActionResult GetName() { 
     return Content(ClaimsPrincipal.Current.FindFirst("name").Value); 
    } 
} 

Và tôi đang cố gắng để thử ClaimsPrincipal tôi với tuyên bố nhưng tôi vẫn không có bất kỳ giá trị giả từ khiếu nại.

// Arrange 
IList<Claim> claimCollection = new List<Claim> 
{ 
    new Claim("name", "John Doe") 
}; 

var identityMock = new Mock<ClaimsIdentity>(); 
identityMock.Setup(x => x.Claims).Returns(claimCollection); 

var cp = new Mock<ClaimsPrincipal>(); 
cp.Setup(m => m.HasClaim(It.IsAny<string>(), It.IsAny<string>())).Returns(true); 
cp.Setup(m => m.Identity).Returns(identityMock.Object); 

var sut = new HomeController(); 

var contextMock = new Mock<HttpContextBase>(); 
contextMock.Setup(ctx => ctx.User).Returns(cp.Object); 

var controllerContextMock = new Mock<ControllerContext>(); 
controllerContextMock.Setup(con => con.HttpContext).Returns(contextMock.Object); 
controllerContextMock.Setup(con => con.HttpContext.User).Returns(cp.Object); 

sut.ControllerContext = controllerContextMock.Object; 

// Act 
var viewresult = sut.GetName() as ContentResult; 

// Assert 
Assert.That(viewresult.Content, Is.EqualTo("John Doe")); 

Viewresult.Content trống khi tôi chạy kiểm tra đơn vị. Bất kỳ trợ giúp nào nếu tôi có thể thêm xác nhận quyền sở hữu giả. Cảm ơn.

Trả lời

15

Đầu tiên, bạn đang thiếu dòng này trong thử nghiệm của bạn:

Thread.CurrentPrincipal = cp.Object; 

(và sau đó làm sạch nó trong TearDown).

Thứ hai, như @trailmax đã đề cập, các đối tượng chính chế nhạo là không thực tế. Trong trường hợp của bạn, ClaimsPrincipal.FindFirst (theo nguồn bị giải mã) nhìn vào các trường riêng của cá thể của nó, đó là lý do mocking không giúp được gì. chức năng

Tôi thích sử dụng hai lớp đơn giản mà cho phép tôi để kiểm tra đơn vị tuyên bố dựa trên:

public class TestPrincipal : ClaimsPrincipal 
    { 
     public TestPrincipal(params Claim[] claims) : base(new TestIdentity(claims)) 
     { 
     } 
    } 

    public class TestIdentity : ClaimsIdentity 
    { 
     public TestIdentity(params Claim[] claims) : base(claims) 
     { 
     } 
    } 

sau đó thử nghiệm của bạn co lại xuống:

[Test] 
    public void TestGetName() 
    { 
     // Arrange 
     var sut = new HomeController(); 
     Thread.CurrentPrincipal = new TestPrincipal(new Claim("name", "John Doe")); 

     // Act 
     var viewresult = sut.GetName() as ContentResult; 

     // Assert 
     Assert.That(viewresult.Content, Is.EqualTo("John Doe")); 
    } 

và bây giờ trôi qua, tôi đã vừa được xác minh.

+0

Cảm ơn! Tôi nghĩ rằng tôi đã làm cho nó phức tạp. Vì vậy, khi nào chúng ta thực sự cần phải giả lập 'ClaimsPrincipal'? Kể từ khi tôi kiểm tra trên google, nhiều người đang chế nhạo 'ClaimsPrincipal'. Chẳng hạn như điều này, http://stackoverflow.com/questions/14190066/is-there-any-way-i-can-mock-a-claims-principal-in-my-asp-net-mvc-web-application. – Henry

+0

Bạn được chào đón :) trong câu trả lời đó, giả định rằng SUT sẽ chỉ gọi phương thức HasClaim, quá mong manh. Nếu một ngày SUT (có thể là mã bên thứ 3) cần truy cập thêm các thành viên của hiệu trưởng, kiểm tra sẽ bị phá vỡ. Tôi thường thích phân lớp phụ theo cách thủ công và triển khai chúng theo cách "thử nghiệm", trong khi tôi đảm bảo chúng vẫn hoạt động một cách nhất quán. –

+0

Brilliant! Làm việc hoàn hảo cho tôi. Cảm ơn bạn! –

13

Bạn không cần phải thử ClaimsPrincipal nó có không phụ thuộc bên ngoài và bạn có thể tạo ra nó bỏ chế giễu:

var claims = new List<Claim>() 
{ 
    new Claim(ClaimTypes.Name, "username"), 
    new Claim(ClaimTypes.NameIdentifier, "userId"), 
    new Claim("name", "John Doe"), 
}; 
var identity = new ClaimsIdentity(claims, "TestAuthType"); 
var claimsPrincipal = new ClaimsPrincipal(identity); 

Và tôi không chắc chắn những gì bạn đang thử nghiệm ở đây. Chắc chắn "John Doe" sẽ không là một phần của viewResult.Content bởi vì nó không bao giờ được thiết lập để điều này.

Các vấn đề liên quan