[英]How to mock UserManager in .NET Core with NUnit?
我想用Razor Pages對使用.NET Core制作的應用程序進行單元測試。 我需要模擬我的dbContext
和我的UserManager
- 但是,我似乎繼續得到null
作為結果。
public class FakeUserManager : UserManager<ApplicationUser>
{
public FakeUserManager()
: base(new Mock<IUserStore<ApplicationUser>>().Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<IPasswordHasher<ApplicationUser>>().Object,
new IUserValidator<ApplicationUser>[0],
new IPasswordValidator<ApplicationUser>[0],
new Mock<ILookupNormalizer>().Object,
new Mock<IdentityErrorDescriber>().Object,
new Mock<IServiceProvider>().Object,
new Mock<ILogger<UserManager<ApplicationUser>>>().Object)
{ }
}
[TestFixture]
public class UserTest
{
private ApplicationDbContext _dbContext { get; set; }
public void TestSetUp()
{
DbContextOptionsBuilder<ApplicationDbContext> optionsbuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
optionsbuilder.UseInMemoryDatabase(databaseName: "TestDB");
_dbContext = new ApplicationDbContext(optionsbuilder.Options);
_dbContext.Users.Add(new ApplicationUser
{
Id = "1",
FirstName = "Test",
LastName = "Alpha",
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now,
});
_dbContext.SaveChanges();
}
[Test]
public void MyTest()
{
Mock<FakeUserManager> fakeUserManager = new Mock<FakeUserManager>();
var result = fakeUserManager.Object.FindByIdAsync("1");
// I know this Assert always returns success, but I'd like var result to return my ApplicationUser found by the FakeUserManager
Assert.AreEqual("test", "test");
}
}
在將這個問題標記為重復之前,是的 - 我會查看其他帖子,但他們不滿足我的答案。
當我運行此測試時, var result
返回null
,我不明白為什么。
[Test]
public async void MyTest()
{
var mockStore = Mock.Of<IUserStore<ApplicationUser>>();
var mockUserManager = new Mock<UserManager<ApplicationUser>>(mockStore, null, null, null, null, null, null, null, null);
var user = new ApplicationUser
{
Id = "1",
FirstName = "Test",
LastName = "Test"
};
mockUserManager
.Setup(x => x.CreateAsync(It.IsAny<ApplicationUser>(), It.IsAny<string>()))
.ReturnsAsync(IdentityResult.Success);
await mockUserManager.Object.CreateAsync(user);
var result = mockUserManager.Object.FindByIdAsync("UserA");
Assert.AreEqual("test", "test");
}
您不應該測試UserManager是否可以從數據庫中檢索數據(這是您的范圍之外的框架的內部問題)。 相反,您應該為UserManager模擬FindByIdAsync的功能,如下所示:
var UserStoreMock = Mock.Of<IUserStore<AppUser>>();
var userMgr = new Mock<UserManager<AppUser>>(UserStoreMock, null, null, null, null, null, null, null, null);
var user = new AppUser() { Id = "f00", UserName = "f00", Email = "f00@example.com" };
var tcs = new TaskCompletionSource<AppUser>();
tcs.SetResult(user);
userMgr.Setup(x => x.FindByIdAsync("f00")).Returns(tcs.Task);
對於您的身份設置,以確保具有適當權限的經過身份驗證的用戶正在進行呼叫:
Mock<ClaimsPrincipal> ClaimsPrincipalMock = new Mock<ClaimsPrincipal>();
ClaimsPrincipalMock.Setup(x => x.IsInRole("Admin")).Returns(true);
ClaimsPrincipalMock.Name = "SomeAdmin";
ClaimsPrincipalMock.SetupGet(x => x.Identity.Name).Returns(ClaimsPrincipalMock.Name);
然后為您的帳戶控制器設置上下文,將UserManager作為DI參數之一傳遞:
AccountController SUT = new AccountController(userMgr);
var context = new ControllerContext();
context.HttpContext = new DefaultHttpContext();
context.HttpContext.User = ClaimsPrincipalMock.Object;
SUT.ControllerContext = context;
最后在你的控制器中,匹配代碼將類似於:
[HttpGet("User")]
public async Task<IActionResult> GetUser(string id)
{
var user = await _userManager.FindByIdAsync(id);
bool isAdmin= User.IsInRole("Admin");
if (user == default(AppUser) || (User.Identity.Name != user.UserName && isAdmin == false))
{
return NotFound();
}
return Ok(user);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.