lundi 29 août 2016

EF, how to implement mapping in a FakeDbSet/Context?

I have implemented a repository pattern, with EF and a seperate mapping class where I set table key ID and relations. In the data context implementation, I reference this mappers to the DbSets.

Mapper:

internal static class ProductMapper
{
    internal static void BuildMapping(DbModelBuilder modelBuilder)
    {
        var tbl = modelBuilder.Entity<Product>();

        //Primary key
        tbl.HasKey(t => t.ID);

        //Table and column mappings
        tbl.ToTable("Product");

        //Relationships
        tbl.HasRequired(t => t.ProductCategory).WithMany(t => t.Products).HasForeignKey(d => d.ProductCategoryID);
    }
}

DBContext

public class ProductContext : DbContext
{
    public ProductContext() : base("ProductDatabase")
    {
        Database.SetInitializer<ProductContext>(null);
        base.Configuration.LazyLoadingEnabled = false;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        var typesToRegister = Assembly.GetAssembly(typeof(Kyocera.ProductServices.DataAccess.EF.Mappers.ComposedPropertyMapper)).GetTypes()
        .Where(type => type.Namespace != null && type.Namespace.Equals(typeof(Kyocera.ProductServices.DataAccess.EF.Mappers.ComposedPropertyMapper).Namespace))
        .Where(type => type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));

        foreach (var type in typesToRegister)
        {
            dynamic configurationInstance = Activator.CreateInstance(type);
            modelBuilder.Configurations.Add(configurationInstance);
        }
    }

    public virtual DbSet<Product> Products { get; set; }
    public virtual DbSet<ProductCategory> ProductCategories { get; set; }
 }

For the unit testing, I have a seperate implementation for the DBContext and DBSets:

FakeDbContext

public abstract class FakeDbContext : IFakeDBContext
{
    #region Private Fields  
    private readonly Dictionary<Type, object> _fakeDbSets;
    #endregion Private Fields

    protected FakeDbContext()
    {
        _fakeDbSets = new Dictionary<Type, object>();
    }

    public int SaveChanges() { return default(int); }

    public void SyncObjectState<TEntity>(TEntity entity) where TEntity : class, IObjectState
    {
        // no implentation needed, unit tests which uses FakeDbContext since there is no actual database for unit tests, 
        // there is no actual DbContext to sync with, please look at the Integration Tests for test that will run against an actual database.
    }

    public Task<int> SaveChangesAsync(CancellationToken cancellationToken) { return new Task<int>(() => default(int)); }

    public Task<int> SaveChangesAsync() { return new Task<int>(() => default(int)); }

    public void Dispose() { }

    public DbSet<T> Set<T>() where T : class { return (DbSet<T>)_fakeDbSets[typeof(T)]; }

    public void AddFakeDbSet<TEntity, TFakeDbSet>()
        where TEntity : Entity, new()
        where TFakeDbSet : FakeDbSet<TEntity>, IDbSet<TEntity>, new()
    {
        var fakeDbSet = Activator.CreateInstance<TFakeDbSet>();
        _fakeDbSets.Add(typeof(TEntity), fakeDbSet);
    }

    public void SyncObjectsStatePostCommit() { }
}

ProductDbContext for unit testing

public class ProductDbContext : FakeDbContext
{
    public ProductDbContext()
    {
        AddFakeDbSet <Product, ProductDbSet>();
        AddFakeDbSet <ProductGroup, ProductGroupDbSet>();
    }
}

public class ProductDbSet : FakeDbSet<Product> { }
public class ProductGroupDbSet : FakeDbSet<ProductGroup> { }

}

Can I use the mapper also in this fake db context? And if yes, where?

Aucun commentaire:

Enregistrer un commentaire