C# 解耦EntityFramework进行单元测试
来源:互联网 发布:dns免费域名 编辑:程序博客网 时间:2024/05/21 08:55
1. 首先EF的Repository需要抽象的行为提到接口中。
public interface IXXXContext : IDisposable { IXXXContext NewInstance();// db sets DbSet<AAABBB> aaa { get; set; }...// common Database Database { get; } DbContextConfiguration Configuration { get; } int SaveChanges(); Task<int> SaveChangesAsync();// store pros... IStorePro1 StorePro1 { get; }...}
然后就可以使用DataContext和TestDataContext实现这个接口。其中TestDataContext是在UT中使用的,DataContext是自动生成的。
TestDataContext还需要以下几个类进行模拟。
public class TestDbSet<TEntity> : DbSet<TEntity>, IQueryable, IEnumerable<TEntity>, IDbAsyncEnumerable<TEntity> where TEntity : class { ObservableCollection<TEntity> _data; IQueryable _query; public TestDbSet() { _data = new ObservableCollection<TEntity>(); _query = _data.AsQueryable(); } public override TEntity Add(TEntity 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<TEntity>(); } public override TDerivedEntity Create<TDerivedEntity>() { return Activator.CreateInstance<TDerivedEntity>(); } public override ObservableCollection<TEntity> Local { get { return _data; } } Type IQueryable.ElementType { get { return _query.ElementType; } } Expression IQueryable.Expression { get { return _query.Expression; } } IQueryProvider IQueryable.Provider { get { return new TestDbAsyncQueryProvider<TEntity>(_query.Provider); } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return _data.GetEnumerator(); } IEnumerator<TEntity> IEnumerable<TEntity>.GetEnumerator() { return _data.GetEnumerator(); } IDbAsyncEnumerator<TEntity> IDbAsyncEnumerable<TEntity>.GetAsyncEnumerator() { return new TestDbAsyncEnumerator<TEntity>(_data.GetEnumerator()); } } internal class TestDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider { private readonly IQueryProvider _inner; internal TestDbAsyncQueryProvider(IQueryProvider inner) { _inner = inner; } public IQueryable CreateQuery(Expression expression) { return new TestDbAsyncEnumerable<TEntity>(expression); } public IQueryable<TElement> CreateQuery<TElement>(Expression expression) { return new TestDbAsyncEnumerable<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)); } } internal class TestDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>, IQueryable<T> { public TestDbAsyncEnumerable(IEnumerable<T> enumerable) : base(enumerable) { } public TestDbAsyncEnumerable(Expression expression) : base(expression) { } public IDbAsyncEnumerator<T> GetAsyncEnumerator() { return new TestDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator()); } IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator() { return GetAsyncEnumerator(); } IQueryProvider IQueryable.Provider { get { return new TestDbAsyncQueryProvider<T>(this); } } } internal class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T> { private readonly IEnumerator<T> _inner; public TestDbAsyncEnumerator(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; } } }
使用示例:
[TestMethod] public void TestMethod1() { var mockSet = new Mock<DbSet<BLACKLISTED_TICKET>>(); var mockContext = new Mock<TicketDataContextTest>(); mockContext.Setup(m => m.BLACKLISTED_TICKET).Returns(new TestDbSet<BLACKLISTED_TICKET>()); var context = mockContext.Object; context.BLACKLISTED_TICKET.Add(new BLACKLISTED_TICKET() { TicketNumber = "aaa", CreatedDateTime = DateTime.Now, Id = 1, ModifiedDateTime = DateTime.Now, STATUS = "1" }); Assert.IsTrue(context.BLACKLISTED_TICKET.First().Id == 1); }
如果使用了存储过程,需要额外定义存储过程的接口。
例如:
IStorePro {...}StorePro : IStorePro{...}StoreProFake: IStorePro{}
然后IDataContext负责返回存储过程的实例
IDataContext{...IStorePro GetStorePro();...}
1 0
- C# 解耦EntityFramework进行单元测试
- C# 单元测试EntityFramework中的DbFunctions中的函数
- C#中使用NUnit进行单元测试
- VS2013进行C#程序的单元测试
- 使用VS2013进行C#程序的单元测试
- 在C#中使用EntityFramework(EF)生成实体进行存储过程的调用
- 在C#中使用EntityFramework(EF)生成实体进行存储过程的调用
- 进行单元测试
- C# Visual Studio环境下进行单元测试【转】【整理】
- EntityFrameWork
- c#单元测试
- C#单元测试
- C# 单元测试
- 利用JUNIT进行单元测试
- 如何进行单元测试
- 使用NUnit进行单元测试
- 利用J2MEUnit进行单元测试
- 使用CppUnit进行单元测试
- Windows下PHP环境搭建
- static静态变量的理解
- 【模板】baby_step giant_step poj 2417
- logstash match
- 位运算【基本运算】
- C# 解耦EntityFramework进行单元测试
- 51nod oj 1400 序列分解 【dfs暴力】
- 网站发帖防注入SQL语句之UBB翻译(正则表达式)
- xCode8终端消息出现异常
- 双栈排序
- 位运算【20个技巧】
- x265源码分析:sao.cpp 自适应样点补偿
- 第三周 项目1 顺序表的基本运算
- IO技术(一)IO技术和File类