Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Identity's Managers in IdentityDbContext that was created by UseInMemoryDatabase()

I made this method to make unit testing DbContext much easier. This method makes Context of my db in memory. It works because i testing it with entities (like _context.Projects, _context.Tests etc., in unit testing, this method works):

        public static TaskManagerDbContext Create()
        {
            var options = new DbContextOptionsBuilder<TaskManagerDbContext>()
                                .UseInMemoryDatabase(Guid.NewGuid().ToString())
                                .EnableSensitiveDataLogging(true)
                                .Options;

            var context = new TaskManagerDbContext(options);
            context.SaveChanges();

            return context;
        }

My DbContextClass looks like this:


    public class TaskManagerDbContext : IdentityDbContext<ApplicationUser>, ITaskManagerDbContext
    {
        public TaskManagerDbContext(DbContextOptions<TaskManagerDbContext> options)
            : base(options)
        {
        }

        //db sets here

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.ApplyConfigurationsFromAssembly(typeof(TaskManagerDbContext).Assembly);
        }
    }

My question is, can we make Identity's UserManager, SignInManager, RoleManager in memory, like we can do with IdentityDbContext? How to unit test Identity things like users, roles in memory like we can do with standard Context? How to call this Managers in fake context that is stored in memory while im testing it?

EDIT:

Based on this SO Question Identity shares context that is obvious. But how to use Managers on created IdentityDbContext by UseInMemoryDatabase() method?

EDIT2:

Im injecting context by fixture:

public class DatabaseFixture
{
    public TaskManagerDbContext Context { get; private set; }

    public DatabaseFixture()
    {
        this.Context = DatabaseContextFactory.Create();
    }
}

[CollectionDefinition("DatabaseTestCollection")]
public class QueryCollection : ICollectionFixture<DatabaseFixture>
{
}

And usage of it:

[Collection("DatabaseTestCollection")]
public class RegisterUserCommandTests
{
    private readonly TaskManagerDbContext _context;

    public RegisterUserCommandTests(DatabaseFixture fixture)
    {
        _context = fixture.Create();
    }

    //and usage of it in class:
    var user = _context.Projects.Find(8);
}

Im using Xunit.

like image 520
michasaucer Avatar asked Sep 13 '25 19:09

michasaucer


1 Answers

You need to create a service collection, register everything with that, and then use that to pull out what you need.

var services = new ServiceCollection();
services.AddDbContext<TaskManagerDbContext>(o =>
    o.UseInMemoryDatabase(Guid.NewGuid()));
services.AddIdentity<IdentityUser, IdentityRole>()
    .AddEntityFrameworkStores<TaskManagerDbContext>();
var provider = services.BuildServiceProvider();

Then, you can use provider:

using (var scope = provider.CreateScope())
{
    var userManager = scope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>();
}
like image 129
Chris Pratt Avatar answered Sep 16 '25 09:09

Chris Pratt