gpt4 book ai didi

c# - User.Identity.GetUserId() Owin Moq 单元测试

转载 作者:太空宇宙 更新时间:2023-11-03 18:59:00 26 4
gpt4 key购买 nike

我有 ChangePassword 方法,我有 User.Identity.GetUserId() 来查找 UserId

Problem: It always return null. Don't understand why.

我在另一篇文章中读到,GetUserById 使用下面的代码行来查找 Id。我不确定如何模拟 ClaimsTypes.NameIdentifier

return ci.FindFirstValue(ClaimTypes.NameIdentifier);

ChangePassword方法(方法待单元测试)

public async Task<IHttpActionResult> ChangePassword(string NewPassword, string OldPassword)
{

_tstService = new TestService();
IdentityResult result = await _tstService.ChangePassword(User.Identity.GetUserId(), OldPassword, NewPassword);

if (!result.Succeeded)
{
return GetErrorResult(result);
}

return Ok();
}

单元测试

var mock = new Mock<MyController>();
mock.CallBase = true;
var obj = mock.Object;

obj.ControllerContext = new HttpControllerContext { Request = new HttpRequestMessage() };
obj.Request.SetOwinContext(CommonCodeHelper.mockOwinContext());

IPrincipal user = GetPrincipal();
obj.ControllerContext.RequestContext.Principal = user;
var result = await obj.ChangePassword(dto);

//获取主体

public static IPrincipal GetPrincipal()
{
var user = new Mock<IPrincipal>();
var identity = new Mock<IIdentity>();
identity.Setup(x => x.Name).Returns("User1@Test.com");
identity.Setup(p => p.IsAuthenticated).Returns(true);

user.Setup(x => x.Identity).Returns(identity.Object);
Thread.CurrentPrincipal = user.Object;
return user.Object;
}

IOwinContext 模拟代码

public static IOwinContext mockOwinContext()
{
var owinMock = new Mock<IOwinContext>();
owinMock.Setup(o => o.Authentication.User).Returns(new ClaimsPrincipal());
owinMock.Setup(o => o.Request).Returns(new Mock<OwinRequest>().Object);
owinMock.Setup(o => o.Response).Returns(new Mock<OwinResponse>().Object);
owinMock.Setup(o => o.Environment).Returns(new Dictionary<string, object> { { "key1", 123 } });
var traceMock = new Mock<TextWriter>();
owinMock.Setup(o => o.TraceOutput).Returns(traceMock.Object);

var userStoreMock = new Mock<IUserStore<IfsUser>>();
userStoreMock.Setup(s => s.FindByIdAsync("User1@ifstoolsuite.com")).ReturnsAsync(new IfsUser
{
Id = "User1@test.com",
FirstName = "Test",
LastName = "User1",
Email = "User1@test.com",
UserName = "User1@test.com",
});
var applicationUserManager = new IfsUserManager(userStoreMock.Object);
owinMock.Setup(o => o.Get<IfsUserManager>(It.IsAny<string>())).Returns(applicationUserManager);
return owinMock.Object;
}

最佳答案

您的 GetPrincipal 可以更新为使用声明。

public static IPrincipal GetPrincipal() {
//use an actual identity fake
var username = "User1@Test.com";
var identity = new GenericIdentity(username, "");
//create claim and add it to indentity
var nameIdentifierClaim = new Claim(ClaimTypes.NameIdentifier, username);
identity.AddClaim(nameIdentifierClaim);

var user = new Mock<IPrincipal>();
user.Setup(x => x.Identity).Returns(identity);
Thread.CurrentPrincipal = user.Object;
return user.Object;
}

下面是一个示例,展示了上述方法的工作原理。

public partial class MiscUnitTests {
[TestClass]
public class IdentityTests : MiscUnitTests {
Mock<IPrincipal> mockPrincipal;
string username = "test@test.com";

[TestInitialize]
public override void Init() {
//Arrange
var identity = new GenericIdentity(username, "");
var nameIdentifierClaim = new Claim(ClaimTypes.NameIdentifier, username);
identity.AddClaim(nameIdentifierClaim);

mockPrincipal = new Mock<IPrincipal>();
mockPrincipal.Setup(x => x.Identity).Returns(identity);
mockPrincipal.Setup(x => x.IsInRole(It.IsAny<string>())).Returns(true);
}

[TestMethod]
public void Should_GetUserId_From_Identity() {

var principal = mockPrincipal.Object;

//Act
var result = principal.Identity.GetUserId();

//Asserts
Assert.AreEqual(username, result);
}

[TestMethod]
public void Identity_Should_Be_Authenticated() {

var principal = mockPrincipal.Object;

//Asserts
Assert.IsTrue(principal.Identity.IsAuthenticated);
}
}
}

您有一些设计问题。创建一个具体的 TestService 如果它连接到一个实际的实现会导致问题。这成为一个集成测试。也抽象该依赖性。

public interface ITestService {
Task<IdentityResult> ChangePassword(string userId, string oldPassword, string newPassword);
}

public abstract class MyController : ApiController {
private ITestService service;

protected MyController(ITestService service) {
this.service = service;
}

public async Task<IHttpActionResult> ChangePassword(string NewPassword, string OldPassword) {

IdentityResult result = await service.ChangePassword(User.Identity.GetUserId(), OldPassword, NewPassword);

if (!result.Succeeded) {
return GetErrorResult(result);
}

return Ok();
}

}

此外,您不应该模拟被测系统。您应该模拟 SUT 的依赖项。根据您要测试的方法以及您在注释中指出 MyController 是一个抽象类,应进行以下测试

[TestClass]
public class MyControllerTests {
public class FakeController : MyController {
public FakeController(ITestService service) : base(service) { }
}

[TestMethod]
public void TestMyController() {
//Arrange
var mockService = new Mock<ITestService>();
mockService
.Setup(m => m.ChangePassword(....))
.ReturnsAsync(....);
var controller = new FakeController(mockService.Object);

//Set a fake request. If your controller creates responses you will need this
controller.Request = new HttpRequestMessage {
RequestUri = new Uri("http://localhost/api/my")
};
controller.Configuration = new HttpConfiguration();
controller.User = GetPrincipal();

//Act
var result = await controller.ChangePassword("NewPassword", "OldPassword");

//Assert
//...
}
}

关于c# - User.Identity.GetUserId() Owin Moq 单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38995597/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com