我想用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");
}
答案 0 :(得分:3)
您不应测试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);
}