MVC5中用于模拟ConfirmEmailAsync和其他UserManager方法的接口

2023-12-04

我正在尝试对这个控制器方法进行单元测试,该方法在当前的 MVC 项目中是开箱即用的。

[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
    if (userId == null || code == null)
    {
        return View("Error");
    }
    var result = await UserManager.ConfirmEmailAsync(userId, code);
    return View(result.Succeeded ? "ConfirmEmail" : "Error");
}

AccountController 有一个构造函数,该构造函数将 ApplicationUserManager 和 ApplicationSignInManager 作为参数,以及带有私有设置器的匹配属性以用于测试。但是,我不知道如何模拟ConfirmEmailAsync 方法。

您可以在 Identity 命名空间中模拟各种接口:

var store = new Mock<IUserStore<ApplicationUser>>();

store.As<IUserEmailStore<ApplicationUser>>()
            .Setup(x => x.FindByIdAsync("username1"))
            .ReturnsAsync((ApplicationUser)null);

var mockManager = new ApplicationUserManager(store.Object);

AccountController ac = new AccountController(mockManager, null, GetMockRepository().Object, GetMockLogger().Object);

但我无法找到或弄清楚我需要哪个接口来创建 ConfirmEmailAsync 的模拟。

我该怎么办?作为参考,是否有一种好方法可以找出这些方法所在的接口以便模拟和测试它们?


ConfirmEmailAsync目前不是框架中接口的一部分。它位于UserManager<TUser, TKey>class 是 Identity 框架的基类。

我的解决方案?

抽象所有事物

我通过将身份的大部分功能抽象到自己的项目中来解决这个问题,以便我可以更轻松地对其进行单元测试并在其他项目中重用该抽象。读完这篇文章后我有了这个想法

持久性无知的 ASP.NET 身份与模式

然后我对这个想法进行了微调以满足我的需要。我基本上只是将 asp.net.identity 中所需的所有内容替换为自定义接口,这些接口或多或少反映了框架提供的功能,但具有更容易模拟的优点。

身份用户

/// <summary>
///  Minimal interface for a user with an id of type <seealso cref="System.String"/>
/// </summary>
public interface IIdentityUser : IIdentityUser<string> { }
/// <summary>
///  Minimal interface for a user
/// </summary>
public interface IIdentityUser<TKey>
    where TKey : System.IEquatable<TKey> {

    TKey Id { get; set; }
    string UserName { get; set; }
    string Email { get; set; }
    bool EmailConfirmed { get; set; }
    string EmailConfirmationToken { get; set; }
    string ResetPasswordToken { get; set; }
    string PasswordHash { get; set; }
}

身份管理器

/// <summary>
/// Exposes user related api which will automatically save changes to the UserStore
/// </summary>
public interface IIdentityManager : IIdentityManager<IIdentityUser> { }
/// <summary>
/// Exposes user related api which will automatically save changes to the UserStore
/// </summary>
public interface IIdentityManager<TUser> : IIdentityManager<TUser, string>
    where TUser : class, IIdentityUser<string> { }
/// <summary>
/// Exposes user related api which will automatically save changes to the UserStore
/// </summary>
public interface IIdentityManager<TUser, TKey> : IDisposable
    where TUser : class, IIdentityUser<TKey>
    where TKey : System.IEquatable<TKey> {

    Task<IIdentityResult> AddPasswordAsync(TKey userid, string password);
    Task<IIdentityResult> ChangePasswordAsync(TKey userid, string currentPassword, string newPassword);
    Task<IIdentityResult> ConfirmEmailAsync(TKey userId, string token);
    //...other code removed for brevity
}

II 身份结果

/// <summary>
/// Represents the minimal result of an identity operation
/// </summary>
public interface IIdentityResult : System.Collections.Generic.IEnumerable<string> {
    bool Succeeded { get; }
}

在身份管理器的默认实现中,我简单地包装了ApplicationManager然后在我的类型和 asp.net.identity 类型之间映射结果和功能。

public class DefaultUserManager : IIdentityManager {
    private ApplicationUserManager innerManager;

    public DefaultUserManager() {
        this.innerManager = ApplicationUserManager.Instance;
    }
    //..other code removed for brevity
    public async Task<IIdentityResult> ConfirmEmailAsync(string userId, string token) {
        var result = await innerManager.ConfirmEmailAsync(userId, token);
        return result.AsIIdentityResult();
    }
    //...other code removed for brevity
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MVC5中用于模拟ConfirmEmailAsync和其他UserManager方法的接口 的相关文章

随机推荐