使用 GetUserASync(用户)的单元测试控制器

Unit Testing Controller that uses GetUserASync (User)

我正在尝试对控制器操作 return 进行单元测试以确保视图正确。我正在使用 .NET Core、Moq 和 NUnit。

我想测试默认 ManageController,

构造函数在下面,

public ManageController(
  UserManager<ApplicationUser> userManager,
  SignInManager<ApplicationUser> signInManager,
  IEmailSender emailSender,
  ILogger<ManageController> logger,
  UrlEncoder urlEncoder)
{
    _userManager = userManager;
    _signInManager = signInManager;
    _emailSender = emailSender;
    _logger = logger;
    _urlEncoder = urlEncoder;
}

我正在尝试对以下 Index 操作进行单元测试,并在成功时断言它 return 是正确的 ViewModel。 (并且将来会添加 return 不同 ViewModels 的其他路径)

[HttpGet]
public async Task<IActionResult> Index()
{
    var user = await _userManager.GetUserAsync(User);
    if (user == null)
    {
        throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
    }

    var model = new IndexViewModel
    {
        Username = user.UserName,
        Email = user.Email,
        PhoneNumber = user.PhoneNumber,
        IsEmailConfirmed = user.EmailConfirmed,
        StatusMessage = StatusMessage
    };

    return View(model);
}

经过多次尝试,我最接近的解决方案如下,

我已经嘲笑,UserManager,并使用 ID 为“1”的 ClaimsPrincipal 设置 GetUserASync 方法。我还将 HttpContext 设置为使用相同的 ClaimsPrincipal 并将其传递给控制器​​。

由于 Action 是异步的,我被迫将测试方法设为异步。目前,由于 returned 的异步 Task 为 null,因此测试失败。我无法查看其余测试是否通过,因为我无法克服此错误。

[Test]
public async Task Index_UserExists_ReturnsViewAsync()
{
     var mockUserStore = new Mock<IUserStore<ApplicationUser>>();
     var mockUserManager = new Mock<UserManager<ApplicationUser>>(mockUserStore.Object, null, null, null, null, null, null, null, null);

    var user = new ClaimsPrincipal(new ClaimsIdentity(new Claim[]
    {
        new Claim(ClaimTypes.NameIdentifier, "1"),
    }));

    mockUserManager.Setup(x => x.GetUserAsync(user));

    var controller = new ManageController(mockUserManager.Object, null, null, null, null)
    {
        ControllerContext = new ControllerContext()
        {
            HttpContext = new DefaultHttpContext() { User = user }
        }
    };

    //Act
    var result = await controller.Index();

    //Assert
    Assert.IsInstanceOf<ViewResult>(result);
}

将模拟设置为 return 任务,以便等待它并允许代码按预期流动

//...

var appUser = new ApplicationUser {
    //...populate as needed
}

 mockUserManager
    .Setup(_ => _.GetUserAsync(user))
    .ReturnsAsync(appUser); // Allows mocked member to be awaited and return desired type

//...