如何在Usermanager类中嘲笑GetUserasync方法



我正在尝试对一个报表控制器进行单位测试,该报告控制器将userManager对象带到构造函数中。

public class ReportController : BaseReportController {
    private readonly IUserService _userService;
    public ReportController ( IOptions<AppSettings> appSettings,
                              UserManager<ApplicationUser> userManager,
                              IUserService userService ) : base( appSettings, userManager ) {
        _userService = userService;
    }
    public async Task<ActionResult> Report ( string path ) {
        var currentUser = await GetCurrentUserAsync();
        var excludedItems = _userService.GetUserExcludedReportsById( currentUser.Id ).Select( er => er.Path );
        if ( string.IsNullOrEmpty( path ) || excludedItems.Any( path.Contains ) ) {
            return RedirectToAction( nameof(HomeController.Index), "Home" );
        }
        var customItems = _userService.GetUserCustomReportsById( currentUser.Id ).Select( er => er.Path );
        if ( path.Contains( AppSettings.CustomReportsFolderName ) && !customItems.Any( path.Contains ) ) {
            return RedirectToAction( nameof(HomeController.Index), "Home" );
        }

        var model = GetReportViewerModel( Request );
        model.Parameters.Clear();
        var dbname = _userService.GetDefaultDbName( (await GetCurrentUserAsync()).Id );
        model.Parameters.Add( "connectionStr", new[] {
            dbname
        } );
        //model.ReportPath = "/Portal Reports" + path;
        model.ReportPath = path;
        model.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Ntlm;
        return View( "Report", model );
    }
}

我认为我需要以某种方式为应用程序用户提供调用。因此,getCurrentUserAsync((将是第一个示例。这将传递到基础:

public virtual Task<ApplicationUser> GetCurrentUserAsync() {
        return UserManager.GetUserAsync(HttpContext.User);
    }

我已经创建了一个假人,但是它仍然在身份部分上错误,但异常。到目前为止,这是我的测试:

[Fact]
    public void ReportControllerReturnsToIndexIfPathIsNull()
    {
        //Arrange
        var context = new Mock<HttpContext>();
        context.Setup(x => x.User).Returns(user.Object);
        var mockUserService = new Mock<IUserService>();           
        AppSettings appSettings = new AppSettings() { };
        IOptions<AppSettings> options = Options.Create(appSettings);
        var mockUserStore = new Mock<IUserStore<ApplicationUser>>();          
        var sut = new ReportController(options, new FakeUserManager(mockUserStore.Object), mockUserService.Object);
        sut.HttpContext = context.Object;         
        //Act
        var result = sut.Report("");            
        //Assert           
    }
}
public class FakeUserManager : UserManager<ApplicationUser>
{
    public FakeUserManager(IUserStore<ApplicationUser> userStore)
        : base(userStore/*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)
    {
    }
    public override Task<ApplicationUser> FindByIdAsync(string id)
    {
        return Task.FromResult(new ApplicationUser { Id = id });
    }
}

我在这里的正确行吗?如何通过此httpcontext.user将其传递?非常感谢。

您不需要模拟GetUserAsync,如果您,实际上更好。您需要的只是模拟HttpContext,以便返回正确的用户。

这是跳跃的障碍,实际上提供了更好的测试。如果嘲笑GetUserAsync,则您正在测试操作的特定实现,即使用GetUserAsync获取用户的操作。如果您稍后决定直接从上下文中获得某些服务类别等。

同时,只要您基于HttpContext查询当前用户,任何方法显然都会使用,因为那是"当前"用户的概念所处的概念,那么您就不会与任何一个实现联系在一起。只要动作以某种方式得到当前用户,它就可以。

update

var controller = new ReportController();
controller.ControllerContext = new ControllerContext
{
    HttpContext = new DefaultHttpContext
    {
        User = new ClaimsPrincipal(new ClaimsIdentity(new Claim[]
        {
            new Claim(ClaimTypes.Name, "foo")
        }));
    }
};

,您可能需要在用户上设置的索赔方面进行一些操作,具体取决于您的代码正在做什么。以上是设置User.Identity.Name的值,对于大多数目的而言,应该足够。标准索赔的完整列表在这里。

相关内容

  • 没有找到相关文章

最新更新