Before I get started, I wanted to first mention that I'm not guaranteeing this is the best approach, but it worked for me. I spent hours searching around and trying various approaches to figure this one out. Pretty much every example I ran across was showing how to mock up UserManager to return a single user (or was for previous versions of Asp.Net), but I wasn't finding anything that showed how to return a list of users that I could use in Asp.Net Core 3.1.
The common thing I kept finding was something like this:
var mockUserManager = new Mock<UserManager<IdentityUser>>();
mockUserManager.Setup(p => p.FindByIdAsync(It.IsAny<string>()))
.ReturnsAsync(new IdentityUser { ... });
However, like I said, I needed it to return a list of users. I'm not going to go through all the different things I tried, because I'm sure some of them were laughable, but I was trying things like .Setup(p => p.Users).Returns... and that just wasn't working.
My Solution
So, instead of mocking UserManager, what I decided to do was create an interface to get the list of users and just mock that interface. I should have thought of it sooner, but I kept trying to emulate the examples I was running across.
Interface
Here's an example interface to get the users:
using Microsoft.AspNetCore.Identity;
using System.Collections.Generic;
using System.Linq;
namespace MockUsersSampleApp.Interfaces
{
public interface IManageUsers
{
List<IdentityUser> GetUsers();
}
public class ManageUsers : IManageUsers
{
private UserManager<IdentityUser> _userManager;
public ManageUsers(UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}
public List<IdentityUser> GetUsers() => _userManager.Users.ToList();
}
}
After adding the interface to your application, don't forget to register it to the ConfigureServices method in the Startup.cs file.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
// Added this for the new interface
services.AddScoped<IManageUsers, ManageUsers>();
services.AddControllersWithViews();
services.AddRazorPages();
}
Controller
Here's a basic example of using it in a controller which would return the users to a View with ViewData.
using Microsoft.AspNetCore.Mvc;
using MockUsersSampleApp.Interfaces;
namespace MockUsersSampleApp.Controllers
{
public class HomeController : Controller
{
private readonly IManageUsers _manageUsers;
public HomeController(IManageUsers manageUsers)
{
_manageUsers = manageUsers;
}
public IActionResult Index()
{
ViewData["userList"] = _manageUsers.GetUsers();
return View();
}
}
}
Test
Now to test it, you just have to mock the interface
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using MockUsersSampleApp.Controllers;
using MockUsersSampleApp.Interfaces;
using Moq;
using Xunit;
using System.Collections.Generic;
namespace MockUsersSampleAppTests.Controllers
{
public class HomeControllerTests
{
[Fact]
public void HomeController_UsersList_ViewData_NotNullTest()
{
var mockManageUsers = new Mock<IManageUsers>();
// Note: Pulling fake user data from private methods down below
mockManageUsers.Setup(p => p.GetUsers()).Returns(GetUsersListTestData());
var controller = new HomeController(mockManageUsers.Object);
var result = controller.Index();
var viewResult = Assert.IsType<ViewResult>(result);
ViewDataDictionary viewData = viewResult.ViewData;
Assert.NotNull(viewData["userList"]);
}
private List<IdentityUser> GetUsersListTestData()
{
var users = new List<IdentityUser>();
users.Add(GetUserTestData());
return users;
}
private IdentityUser GetUserTestData()
{
var user = new IdentityUser()
{
Id = "1234",
UserName = "user@test.com"
};
return user;
}
}
}
In case you'd like to see more detailed examples of this code, I've uploaded a sample project to my GitHub account at: https://github.com/ElliottBrand/MockUserSampleApp
Hopefully you found this post helpful!