Created
October 13, 2014 07:49
-
-
Save kevingoos/36718ff9670aad9c4f2e to your computer and use it in GitHub Desktop.
FakeDb: Mocking database in a test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class ConexioEntityBL<TE, TC, TG> | |
| { | |
| private readonly UserEnvironmentConfiguration[] _configurations; | |
| private readonly SynchronizationUnitOfWork _unitOfWork; | |
| public async Task<int> GetDoubtfulsCountAsync(CancellationToken cancellationToken, SearchParameters searchParameters) | |
| { | |
| return await new SearchDoubtfuls<TC, TG>(_configurations, _unitOfWork.RepositoryProvider.DataContext).SearchCountAsync(cancellationToken, searchParameters); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Data.Entity.Infrastructure; | |
| using System.Linq; | |
| using System.Linq.Expressions; | |
| using System.Text; | |
| using System.Threading.Tasks; | |
| namespace Repository.Pattern.Ef6.FakeDb | |
| { | |
| internal class FakeDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>, IQueryable<T> | |
| { | |
| public FakeDbAsyncEnumerable(IEnumerable<T> enumerable) | |
| : base(enumerable) | |
| { } | |
| public FakeDbAsyncEnumerable(Expression expression) | |
| : base(expression) | |
| { } | |
| public IDbAsyncEnumerator<T> GetAsyncEnumerator() | |
| { | |
| return new FakeDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator()); | |
| } | |
| IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator() | |
| { | |
| return GetAsyncEnumerator(); | |
| } | |
| IQueryProvider IQueryable.Provider | |
| { | |
| get { return new FakeDbAsyncQueryProvider<T>(this); } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Data.Entity.Infrastructure; | |
| using System.Linq; | |
| using System.Text; | |
| using System.Threading; | |
| using System.Threading.Tasks; | |
| namespace Repository.Pattern.Ef6.FakeDb | |
| { | |
| internal class FakeDbAsyncEnumerator<T> : IDbAsyncEnumerator<T> | |
| { | |
| private readonly IEnumerator<T> _inner; | |
| public FakeDbAsyncEnumerator(IEnumerator<T> inner) | |
| { | |
| _inner = inner; | |
| } | |
| public void Dispose() | |
| { | |
| _inner.Dispose(); | |
| } | |
| public Task<bool> MoveNextAsync(CancellationToken cancellationToken) | |
| { | |
| return Task.FromResult(_inner.MoveNext()); | |
| } | |
| public T Current | |
| { | |
| get { return _inner.Current; } | |
| } | |
| object IDbAsyncEnumerator.Current | |
| { | |
| get { return Current; } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| namespace Repository.Pattern.Ef6.FakeDb | |
| { | |
| internal class FakeDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider | |
| { | |
| private readonly IQueryProvider _inner; | |
| internal FakeDbAsyncQueryProvider(IQueryProvider inner) | |
| { | |
| _inner = inner; | |
| } | |
| public IQueryable CreateQuery(Expression expression) | |
| { | |
| return new FakeDbAsyncEnumerable<TEntity>(expression); | |
| } | |
| public IQueryable<TElement> CreateQuery<TElement>(Expression expression) | |
| { | |
| return new FakeDbAsyncEnumerable<TElement>(expression); | |
| } | |
| public object Execute(Expression expression) | |
| { | |
| return _inner.Execute(expression); | |
| } | |
| public TResult Execute<TResult>(Expression expression) | |
| { | |
| return _inner.Execute<TResult>(expression); | |
| } | |
| public Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken) | |
| { | |
| return Task.FromResult(Execute(expression)); | |
| } | |
| public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken) | |
| { | |
| return Task.FromResult(Execute<TResult>(expression)); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| namespace Repository.Pattern.Ef6.FakeDb | |
| { | |
| public interface IFakeDbContext : IDataContextAsync | |
| { | |
| DbSet<T> Set<T>() where T : class; | |
| void AddFakeDbSet<TEntity, TFakeDbSet>() | |
| where TEntity : Entity, new() | |
| where TFakeDbSet : FakeDbSet<TEntity>, IDbSet<TEntity>, new(); | |
| } | |
| 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() { } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| namespace Repository.Pattern.Ef6.FakeDb | |
| { | |
| public abstract class FakeDbSet<TEntity> : DbSet<TEntity>, IEnumerable<TEntity>, IQueryable where TEntity : Entity, new() | |
| { | |
| #region Private Fields | |
| private readonly ObservableCollection<TEntity> _items; | |
| private readonly IQueryable _query; | |
| #endregion Private Fields | |
| protected FakeDbSet() | |
| { | |
| _items = new ObservableCollection<TEntity>(); | |
| _query = _items.AsQueryable(); | |
| } | |
| public override TEntity Add(TEntity entity) | |
| { | |
| _items.Add(entity); | |
| return entity; | |
| } | |
| public override TEntity Remove(TEntity entity) | |
| { | |
| _items.Remove(entity); | |
| return entity; | |
| } | |
| public override TEntity Attach(TEntity entity) | |
| { | |
| switch (entity.ObjectState) | |
| { | |
| case ObjectState.Modified: | |
| _items.Remove(entity); | |
| _items.Add(entity); | |
| break; | |
| case ObjectState.Deleted: | |
| _items.Remove(entity); | |
| break; | |
| case ObjectState.Unchanged: | |
| case ObjectState.Added: | |
| _items.Add(entity); | |
| break; | |
| default: | |
| throw new ArgumentOutOfRangeException(); | |
| } | |
| return entity; | |
| } | |
| public override TEntity Create() | |
| { | |
| return new TEntity(); | |
| } | |
| public override TDerivedEntity Create<TDerivedEntity>() | |
| { | |
| return Activator.CreateInstance<TDerivedEntity>(); | |
| } | |
| public override ObservableCollection<TEntity> Local | |
| { | |
| get | |
| { | |
| return _items; | |
| } | |
| } | |
| IEnumerator<TEntity> IEnumerable<TEntity>.GetEnumerator() | |
| { | |
| return _items.GetEnumerator(); | |
| } | |
| Type IQueryable.ElementType | |
| { | |
| get | |
| { | |
| return _items.AsQueryable().ElementType; | |
| } | |
| } | |
| Expression IQueryable.Expression | |
| { | |
| get | |
| { | |
| return _items.AsQueryable().Expression; | |
| } | |
| } | |
| IQueryProvider IQueryable.Provider | |
| { | |
| get | |
| { | |
| return _items.AsQueryable().Provider; | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| namespace Conexio.Core.Orchestration.Test.Mock | |
| { | |
| public class MockDbContext : FakeDbContext | |
| { | |
| public MockDbContext() | |
| { | |
| AddFakeDbSet<Data.Entities.InformationService, MockDbSet<Data.Entities.InformationService>>(); | |
| AddFakeDbSet<Environment, MockDbSet<Environment>>(); | |
| AddFakeDbSet<ConexioContact, MockDbSet<ConexioContact>>(); | |
| //INIT DATA | |
| InitData(); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| namespace Conexio.Core.Orchestration.Test.Mock | |
| { | |
| public class MockDbSet<TEntity> : FakeDbSet<TEntity> | |
| where TEntity : Entity, new() | |
| { | |
| public MockDbSet() | |
| { | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [TestClass] | |
| public class SearchContactsTest | |
| { | |
| private SynchronizationUnitOfWork _unitOfWork; | |
| private UserEnvironmentConfiguration[] _configs; | |
| [TestInitialize] | |
| public void Init() | |
| { | |
| _unitOfWork = new SynchronizationUnitOfWork(new MockDbContext()); | |
| _configs = _unitOfWork.UserEnvironmentConfigurationsRepository.Queryable().ToArray(); | |
| } | |
| [TestMethod] | |
| public void TestSearch1() | |
| { | |
| var contactsBl = new ConexioEntityBL<ExternalContact, ConexioContact, Contact>(_configs, _unitOfWork); | |
| //Object[] searchObject = new object[2] { "", true }; | |
| var parameters = new SearchParameters { SearchText = null, HandledType = HandledType.Doubtful }; | |
| var doubtfulContacts = contactsBl.SearchDoubtfulsAsync(0, 0, CancellationToken.None, parameters); | |
| var countSearchDoubtfulContacts = doubtfulContacts.Result.Count(); | |
| var countExisting = _unitOfWork.ContactsRepository.Queryable().Count(); | |
| Assert.AreEqual(countExisting, countSearchDoubtfulContacts); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class SearchDoubtfuls<TC, TG> | |
| where TC : class, IInternalConexioEntity, IObjectState, IConexioEntityAccept | |
| where TG : ConexioEntity | |
| { | |
| private readonly UserEnvironmentConfiguration[] _configurations; | |
| private readonly IDataContextAsync _context; | |
| public async Task<List<ConexioComparisonEntity>> SearchAsync(int page, int count, CancellationToken cancellationToken, SearchParameters searchParameters) | |
| { | |
| var result = new List<ConexioComparisonEntity>(); | |
| var entities = CreateSearchquery(searchParameters); | |
| entities = entities.OrderBy(x => x.ID).Skip(page).Take(count); | |
| //The line that it crashes because ToListAsync is async. | |
| var contactsList = await entities.ToListAsync(cancellationToken); | |
| foreach (var synchronizationContact in contactsList) | |
| { | |
| if (cancellationToken.IsCancellationRequested) return result; | |
| result.Add(ConvertEntity(synchronizationContact)); | |
| } | |
| return result; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment