집 >백엔드 개발 >C#.Net 튜토리얼 >C#은 단위 테스트를 위해 EntityFramework를 분리합니다.
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(); ... }
위는 단위 테스트를 위한 C# 디커플링 EntityFramework의 내용입니다. . 더 많은 관련 정보를 원하시면 PHP 중국어 홈페이지(www.php.cn)를 팔로우해주세요!