簡體   English   中英

如何使用NUnit在.NET Core中模擬UserManager?

[英]How to mock UserManager in .NET Core with NUnit?

我想用Razor Pages對使用.NET Core制作的應用程序進行單元測試。 我需要模擬我的dbContext和我的UserManager - 但是,我似乎繼續得到null作為結果。

FakeUserManager

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)
    { }
}

我的TestClass

 [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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM