Skip to content

Instantly share code, notes, and snippets.

@kevingoos
Created October 13, 2014 07:49
Show Gist options
  • Select an option

  • Save kevingoos/36718ff9670aad9c4f2e to your computer and use it in GitHub Desktop.

Select an option

Save kevingoos/36718ff9670aad9c4f2e to your computer and use it in GitHub Desktop.
FakeDb: Mocking database in a test
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);
}
}
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); }
}
}
}
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; }
}
}
}
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));
}
}
}
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() { }
}
}
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;
}
}
}
}
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();
}
}
}
namespace Conexio.Core.Orchestration.Test.Mock
{
public class MockDbSet<TEntity> : FakeDbSet<TEntity>
where TEntity : Entity, new()
{
public MockDbSet()
{
}
}
}
[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);
}
}
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