簡體   English   中英

Asp .Net Core 單元測試模擬 UserManager.CreateAsync 並返回標識結果

[英]Asp .Net Core Unit Test Mock UserManager.CreateAsync and return Identity Result

在 .Net Core 項目上工作並創建以下服務以在頁面之間共享通用方法。

namespace MyApp.Tests.Services
{
    public class UserServiceTest
    {
        [Fact]
        public async Task CreateUser_ShouldCreateUser()
        {
            var user = new UserResponse
            {
                Id = "111",
                Email = "john@email.com",
                FirstName = "John",
                LastName = "Doe",
                CompanyName = "SomeCompany",
                PhoneNumber = "9123456789"
            };

            var appUser = new ApplicationUser
            {
                UserName = user.Email,
                Email = user.Email,
                FirstName = user.FirstName,
                LastName = user.LastName,
                CompanyName = user.CompanyName,
                PhoneNumber = user.PhoneNumber
            };

            var logger = Mock.Of<ILogger<UserService>>();
            var mockUserStore = new Mock<IUserStore<ApplicationUser>>();
            mockUserStore
                .Setup(x => x.CreateAsync(appUser, CancellationToken.None))
                .ReturnsAsync(IdentityResult.Success).Verifiable();

            // Tried this one as well but still getting null instead of IdentityResult
            // mockUserStore
            //     .Setup(x => x.CreateAsync(appUser, CancellationToken.None))
            //     .ReturnsAsync(new IdentityResultMock(true));

            var userManager = new UserManager<ApplicationUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);
            var _userService = new UserService(userManager, logger);

            var result = await _userService.CreateUserInApp(user);

            Assert.True(result.Succeeded);
        }
    }

    public class IdentityResultMock : IdentityResult
    {
        public IdentityResultMock(bool succeeded) {
            base.Succeeded = succeeded;
         }
    }
}

還為這個服務編寫了單元測試用例,如下所示來測試 UserService

namespace MyApp.Tests.Services
{
    public class UserServiceTest
    {
        [Fact]
        public async Task CreateUser_ShouldCreateUser()
        {
            var user = new UserResponse
            {
                Id = "111",
                Email = "john@email.com",
                FirstName = "John",
                LastName = "Doe",
                CompanyName = "SomeCompany",
                PhoneNumber = "9123456789"
            };

            var appUser = new ApplicationUser
            {
                UserName = user.Email,
                Email = user.Email,
                FirstName = user.FirstName,
                LastName = user.LastName,
                CompanyName = user.CompanyName,
                PhoneNumber = user.PhoneNumber
            };

            var logger = Mock.Of<ILogger<UserService>>();
            var mockUserStore = new Mock<IUserStore<ApplicationUser>>();
            mockUserStore
                .Setup(x => x.CreateAsync(appUser, CancellationToken.None))
                .ReturnsAsync(IdentityResult.Success).Verifiable(); ;

            var userManager = new UserManager<ApplicationUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);
            var _userService = new UserService(userManager, logger);

            var result = await _userService.CreateUserInApp(user);

            Assert.True(result.Succeeded);
        }
    }
}

在用戶服務中運行測試時

var createResult = await _userManager.CreateAsync(appUser);

createResult 由於此測試用例失敗並獲得空引用異常,我得到空值。 如果我可以從模擬 CreateAsync 設置返回 IdentityResult ,那么它會通過,但不確定我在做什么錯。 也無法創建 IdentityResult 的對象,因為“Succeeded”受保護且無法顯式分配值。 請幫忙。 謝謝 :)

我們需要看看構造函數內部發生了什么:

var userManager = new UserManager<ApplicationUser>(mockUserStore.Object, null, null, null, null, null, null, null, null);

但不是真的。 如果你在這里測試UserService ,那么你應該嘲笑的是UserManager而不是它的內部依賴IUserStore

這是為什么? 因為UserManager的內部結構可能會更改,然后您必須更改UserManager測試和UserService測試。

像創建IUserStore一樣模擬UserManager的創建,您會看到它是 UserStore 中的其他一些依賴項,或者完全超出單元測試范圍的某個地方。

編輯 1

我想我想出了你的問題:

mockUserStore
    .Setup(x => x.CreateAsync(appUser, CancellationToken.None))
    .ReturnsAsync(IdentityResult.Success).Verifiable();

和調用

var result = await _userService.CreateUserInApp(user);

User 對象和 appUser 對象不一樣,因此 mocking 框架不會返回預期值。

為了確保這是問題所在,請嘗試模擬

mockUserStore
    .Setup(x => x.CreateAsync(It.IsAny<ApplicationUser>(), It.IsAny<CancellationToken>()))
    .ReturnsAsync(IdentityResult.Success).Verifiable();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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