Fake DbContext of Entity Framework 4.1 to Test

前端 未结 5 1815
再見小時候
再見小時候 2020-11-22 17:19

I\'m using this tutorial to Fake my DbContext and test: http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/

5条回答
  •  攒了一身酷
    2020-11-22 17:44

    I know we shouldn't do it but sometimes you have to anyway (your boss might ask you too for instance and wouldn't change his mind).

    So as I had to do it I leave it here it might help some people. I'm quite new to c# / .net and all so it's far from being optimized/clean I suppose but it seems to work.

    following MSDN Find here the missing class and using a bit of reflection I managed to add one way properties : Key elements here are the AddNavigationProperty and RefreshNavigationProperties. If anyone has suggestion to improve this code I'll gladly take them

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using System.Linq;
    using System.Linq.Expressions;
    
    namespace MockFactory
    {
        public class TestDbSet : DbSet, IQueryable, IEnumerable, IDbAsyncEnumerable
            where TEntity : class
        {
            public readonly ObservableCollection _data;
            private readonly IQueryable _query;
            private readonly Dictionary entities;
    
            public TestDbSet()
            {
                _data = new ObservableCollection();
                _query = _data.AsQueryable();
    
                entities = new Dictionary();
            }
    
            public override ObservableCollection Local
            {
                get { return _data; }
            }
    
            IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
            {
                return new TestDbAsyncEnumerator(_data.GetEnumerator());
            }
    
            IEnumerator IEnumerable.GetEnumerator()
            {
                return _data.GetEnumerator();
            }
    
            Type IQueryable.ElementType
            {
                get { return _query.ElementType; }
            }
    
            Expression IQueryable.Expression
            {
                get { return _query.Expression; }
            }
    
            IQueryProvider IQueryable.Provider
            {
                get { return new TestDbAsyncQueryProvider(_query.Provider); }
            }
    
            IEnumerator IEnumerable.GetEnumerator()
            {
                return _data.GetEnumerator();
            }
    
            public void AddNavigationProperty(DbSet dbSet) where T : class
            {
                entities.Add(typeof (T), dbSet);
            }
    
            public void RefreshNavigationProperty(TEntity item)
            {
                foreach (var entity in entities)
                {
                    var property = item.GetType().GetProperty(entity.Key.Name);
    
                    var type =
                        (int)item.GetType().GetProperty(entity.Key.Name.Replace(typeof(TEntity).Name, "")).GetValue(item);
    
                    var dbSets = (IEnumerable)entity.Value.GetType().GetField("_data").GetValue(entity.Value);
    
                    var dbSet = dbSets.Single(x => (int)x.GetType().GetProperty("Id").GetValue(x) == type);
                    property.SetValue(item, dbSet);
                }
            }
    
            public override TEntity Add(TEntity item)
            {
                RefreshNavigationProperty(item);
                _data.Add(item);
                return item;
            }
    
            public override TEntity Remove(TEntity item)
            {
                _data.Remove(item);
                return item;
            }
    
            public override TEntity Attach(TEntity item)
            {
                _data.Add(item);
                return item;
            }
    
            public override TEntity Create()
            {
                return Activator.CreateInstance();
            }
    
            public override TDerivedEntity Create()
            {
                return Activator.CreateInstance();
            }
        }
    }
    
    
    

    You can then create your context

     public TestContext()
            {
                TypeUsers = new TestDbSet();
                StatusUsers = new TestDbSet();
    
                TypeUsers.Add(new TypeUser {Description = "FI", Id = 1});
                TypeUsers.Add(new TypeUser {Description = "HR", Id = 2});
    
                StatusUsers.Add(new StatusUser { Description = "Created", Id = 1 });
                StatusUsers.Add(new StatusUser { Description = "Deleted", Id = 2 });
                StatusUsers.Add(new StatusUser { Description = "PendingHR", Id = 3 });
    
    
                Users = new TestDbSet();
    
                ((TestDbSet) Users).AddNavigationProperty(StatusUsers);
               ((TestDbSet)Users).AddNavigationProperty(TypeUsers);
    
            }
    
            public override DbSet TypeUsers { get; set; }
            public override DbSet StatusUsers { get; set; }
            public override DbSet Users { get; set; }
            public int SaveChangesCount { get; private set; }
    
            public override int SaveChanges(string modifierId)
            {
                SaveChangesCount++;
                return 1;
            }
        }
    

    Finally do not forget in your test to refresh the navigation properties before doing the assert (there should be a better way but I couldn't find it )

    ContextFactory.Entity.Users.Each(((TestDbSet) ContextFactory.Entity.Users).RefreshNavigationProperty);
    

    提交回复
    热议问题