如何在模拟 ClaimsPrincipal 中添加声明
How to add claims in a mock ClaimsPrincipal
我正在尝试对从 ClaimsPrincipal.Current 获取信息的控制器代码进行单元测试。
在控制器代码中 I
public class HomeController {
public ActionResult GetName() {
return Content(ClaimsPrincipal.Current.FindFirst("name").Value);
}
}
我正在尝试用声明模拟我的 ClaimsPrincipal,但我仍然没有从声明中获得任何模拟值。
// 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 是空的,因为我 运行 单元测试。如果我可以添加模拟声明,任何帮助。谢谢
您无需模拟 ClaimsPrincipal
它没有外部依赖项,您可以在未模拟的情况下创建它:
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);
而且我不确定您在这里测试的是什么。当然 "John Doe" 不会成为 viewResult.Content
的一部分,因为它从未被设置为这个。
首先,您在测试中遗漏了这一行:
Thread.CurrentPrincipal = cp.Object;
(然后在 TearDown 中清理它)。
其次,正如@trailmax 提到的,模拟主体对象是不切实际的。在您的情况下,ClaimsPrincipal.FindFirst
(根据反编译源)查看其实例的私有字段,这就是模拟没有帮助的原因。
我更喜欢使用两个简单的 类,它们允许我对基于声明的功能进行单元测试:
public class TestPrincipal : ClaimsPrincipal
{
public TestPrincipal(params Claim[] claims) : base(new TestIdentity(claims))
{
}
}
public class TestIdentity : ClaimsIdentity
{
public TestIdentity(params Claim[] claims) : base(claims)
{
}
}
然后你的测试缩小到:
[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"));
}
现在通过了,我刚刚验证了。
我正在尝试对从 ClaimsPrincipal.Current 获取信息的控制器代码进行单元测试。 在控制器代码中 I
public class HomeController {
public ActionResult GetName() {
return Content(ClaimsPrincipal.Current.FindFirst("name").Value);
}
}
我正在尝试用声明模拟我的 ClaimsPrincipal,但我仍然没有从声明中获得任何模拟值。
// 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 是空的,因为我 运行 单元测试。如果我可以添加模拟声明,任何帮助。谢谢
您无需模拟 ClaimsPrincipal
它没有外部依赖项,您可以在未模拟的情况下创建它:
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);
而且我不确定您在这里测试的是什么。当然 "John Doe" 不会成为 viewResult.Content
的一部分,因为它从未被设置为这个。
首先,您在测试中遗漏了这一行:
Thread.CurrentPrincipal = cp.Object;
(然后在 TearDown 中清理它)。
其次,正如@trailmax 提到的,模拟主体对象是不切实际的。在您的情况下,ClaimsPrincipal.FindFirst
(根据反编译源)查看其实例的私有字段,这就是模拟没有帮助的原因。
我更喜欢使用两个简单的 类,它们允许我对基于声明的功能进行单元测试:
public class TestPrincipal : ClaimsPrincipal
{
public TestPrincipal(params Claim[] claims) : base(new TestIdentity(claims))
{
}
}
public class TestIdentity : ClaimsIdentity
{
public TestIdentity(params Claim[] claims) : base(claims)
{
}
}
然后你的测试缩小到:
[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"));
}
现在通过了,我刚刚验证了。