[英]User.Identity.GetUserId() Owin Moq unit test
我有ChangePassword
方法,其中有User.Identity.GetUserId()
來查找UserId
。
問題:它總是返回null。 不明白為什么。
我在另一篇文章中讀到, GetUserById
使用下面的代碼行來查找Id
。 我不確定如何模擬ClaimsTypes.NameIdentifier
。
返回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);
// GetPrincipal
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
//...
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.