I am trying to unit test a Reports controller that takes a UserManager object in the constructor.
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 ); } } I think I need to somehow provide an application user to call this. So GetCurrentUserAsync() would be the first example. This passes to the base:
public virtual Task<ApplicationUser> GetCurrentUserAsync() { return UserManager.GetUserAsync(HttpContext.User); } I have created a FakeUserManager, but it still errors on the identity parts with a null exception. This is my test so far:
[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 }); } } Am i on the right line here? How can I pass this a httpcontext.user? Many thanks.