Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在MVC5中模拟ConfirmMailAsync和其他UserManager方法的接口_C#_Asp.net Mvc_Unit Testing_Asp.net Mvc 5_Asp.net Identity - Fatal编程技术网

C# 在MVC5中模拟ConfirmMailAsync和其他UserManager方法的接口

C# 在MVC5中模拟ConfirmMailAsync和其他UserManager方法的接口,c#,asp.net-mvc,unit-testing,asp.net-mvc-5,asp.net-identity,C#,Asp.net Mvc,Unit Testing,Asp.net Mvc 5,Asp.net Identity,我正在尝试对这个控制器方法进行单元测试,它在当前的MVC项目中是现成的 [AllowAnonymous] public async Task<ActionResult> ConfirmEmail(string userId, string code) { if (userId == null || code == null) { return View("Error"); } var result = await UserManager

我正在尝试对这个控制器方法进行单元测试,它在当前的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");
}
[AllowAnonymous]
公共异步任务确认邮件(字符串用户ID、字符串代码)
{
if(userId==null | | code==null)
{
返回视图(“错误”);
}
var result=await UserManager.confirmemailsync(userId,code);
返回视图(result.successed?“确认邮件”:“错误”);
}
AccountController有一个构造函数,该构造函数将ApplicationUserManager和ApplicationSignInManager作为参数,并具有用于测试的与私有setter匹配的属性。但是,我不知道如何模拟confirmemailsync方法

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

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);
var store=new Mock();
store.As()
.Setup(x=>x.FindByIdAsync(“用户名1”))
.ReturnsAsync((ApplicationUser)null);
var mockManager=新的ApplicationUserManager(store.Object);
AccountController ac=新的AccountController(mockManager,null,GetMockRepository().Object,GetMockLogger().Object);
但我无法找到或弄清楚创建confirmeailasync模拟所需的接口


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

confirmemailsync
目前不是框架中接口的一部分。它位于身份框架的基类
UserManager
类中

我的解决方案

抽象所有事物

我通过将identity的大部分功能抽象到它自己的项目中来解决这个问题,这样我就可以更容易地进行单元测试,并在其他项目中重用抽象。我读了这篇文章后有了这个想法

然后我对这个想法进行了微调,以满足我的需要。我基本上只是将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; }
}

免责声明:我在Typemock工作

实际上,如果正在使用,则不需要任何接口,只需伪造所需的IdentityResult并更改异步方法“ConfirmEmailAsync”的行为,例如,检查未确认电子邮件场景的测试:

[TestMethod, Isolated]
public async Task TestWhenEmailIsBad_ErrorMessageIsShown()
{

    // Arrange
    // Create the wanted controller for testing and fake IdentityResult
    var controller = new aspdotNetExample.Controllers.AccountController();
    var fakeIdentityRes = Isolate.Fake.Instance<IdentityResult>();

    // Fake HttpContext to return a fake ApplicationSignInManager
    var fakeSIM = Isolate.WhenCalled(() => controller.UserManager).ReturnRecursiveFake();

    // Modifying the behavior of ConfirmEmailAsync to return fakeIdentityRes
    Isolate.WhenCalled(() => fakeSIM.ConfirmEmailAsync("", "")).WillReturn(Task.FromResult<IdentityResult>(fakeIdentityRes));
    Isolate.WhenCalled(() => fakeIdentityRes.Succeeded).WillReturn(false);

    // Act
    var result = await controller.ConfirmEmail("", "") as ViewResult;

    // Assert
    Assert.AreEqual("Error", result.ViewName);
}    
[测试方法,隔离]
公共异步任务TestWheneAlisBad\u ErrorMessageIsShown()时
{
//安排
//创建想要的控制器以进行测试并伪造IdentityResult
var controller=new aspdotNetExample.Controllers.AccountController();
var fakeidentiretries=Isolate.Fake.Instance();
//假HttpContext返回假ApplicationSignInManager
var fakeSIM=Isolate.WhenCalled(()=>controller.UserManager).ReturnRecursiveFake();
//修改ConfirmMailAsync的行为以返回FakeIndication
隔离.WhenCalled(()=>fakeSIM.confirmeailasync(“,”).WillReturn(Task.FromResult(fakeidentiretries));
隔离。当被调用时(()=>fakeidentity.successed)。将返回(false);
//表演
var result=await controller.ConfirmEmail(“,”)作为ViewResult;
//断言
Assert.AreEqual(“错误”,result.ViewName);
}    

我通过将identity的大部分功能抽象到自己的项目中来解决这个问题,这样我可以更容易地对其进行单元测试,并在其他项目中重用抽象。我从这篇文章开始,然后根据我的需要对它进行了微调
/// <summary>
/// Represents the minimal result of an identity operation
/// </summary>
public interface IIdentityResult : System.Collections.Generic.IEnumerable<string> {
    bool Succeeded { get; }
}
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
}
[TestMethod, Isolated]
public async Task TestWhenEmailIsBad_ErrorMessageIsShown()
{

    // Arrange
    // Create the wanted controller for testing and fake IdentityResult
    var controller = new aspdotNetExample.Controllers.AccountController();
    var fakeIdentityRes = Isolate.Fake.Instance<IdentityResult>();

    // Fake HttpContext to return a fake ApplicationSignInManager
    var fakeSIM = Isolate.WhenCalled(() => controller.UserManager).ReturnRecursiveFake();

    // Modifying the behavior of ConfirmEmailAsync to return fakeIdentityRes
    Isolate.WhenCalled(() => fakeSIM.ConfirmEmailAsync("", "")).WillReturn(Task.FromResult<IdentityResult>(fakeIdentityRes));
    Isolate.WhenCalled(() => fakeIdentityRes.Succeeded).WillReturn(false);

    // Act
    var result = await controller.ConfirmEmail("", "") as ViewResult;

    // Assert
    Assert.AreEqual("Error", result.ViewName);
}