C# decouples EntityFramework for unit testing

黄舟
Release: 2017-02-28 11:18:24
Original
1951 people have browsed it

1. First of all, EF's Repository needs abstract behavior to be mentioned in the interface.

For example:

public interface IXXXContext : IDisposable
    {
        IXXXContext NewInstance();
// db sets
        DbSet aaa { get; set; }
...
// common 
Database Database { get; }
        DbContextConfiguration Configuration { get; }
        int SaveChanges();


        Task SaveChangesAsync();


	// store pros
...
        IStorePro1 StorePro1 { get; }
	...
}
Copy after login


Then you can use DataContext and TestDataContext to implement this interface. Among them, TestDataContext is used in UT, and DataContext is automatically generated.

TestDataContext also requires the following classes for simulation.

 public class TestDbSet : DbSet, IQueryable, IEnumerable, IDbAsyncEnumerable
         where TEntity : class
    {
        ObservableCollection _data;
        IQueryable _query;


        public TestDbSet()
        {
            _data = new ObservableCollection();
            _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();
        }


        public override TDerivedEntity Create()
        {
            return Activator.CreateInstance();
        }


        public override ObservableCollection 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(_query.Provider); }
        }


        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _data.GetEnumerator();
        }


        IEnumerator IEnumerable.GetEnumerator()
        {
            return _data.GetEnumerator();
        }


        IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
        {
            return new TestDbAsyncEnumerator(_data.GetEnumerator());
        }
    }


    internal class TestDbAsyncQueryProvider : IDbAsyncQueryProvider
    {
        private readonly IQueryProvider _inner;


        internal TestDbAsyncQueryProvider(IQueryProvider inner)
        {
            _inner = inner;
        }


        public IQueryable CreateQuery(Expression expression)
        {
            return new TestDbAsyncEnumerable(expression);
        }


        public IQueryable CreateQuery(Expression expression)
        {
            return new TestDbAsyncEnumerable(expression);
        }


        public object Execute(Expression expression)
        {
            return _inner.Execute(expression);
        }


        public TResult Execute(Expression expression)
        {
            return _inner.Execute(expression);
        }


        public Task ExecuteAsync(Expression expression, CancellationToken cancellationToken)
        {
            return Task.FromResult(Execute(expression));
        }


        public Task ExecuteAsync(Expression expression, CancellationToken cancellationToken)
        {
            return Task.FromResult(Execute(expression));
        }
    }


    internal class TestDbAsyncEnumerable : EnumerableQuery, IDbAsyncEnumerable, IQueryable
    {
        public TestDbAsyncEnumerable(IEnumerable enumerable)
            : base(enumerable)
        { }


        public TestDbAsyncEnumerable(Expression expression)
            : base(expression)
        { }


        public IDbAsyncEnumerator GetAsyncEnumerator()
        {
            return new TestDbAsyncEnumerator(this.AsEnumerable().GetEnumerator());
        }


        IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
        {
            return GetAsyncEnumerator();
        }


        IQueryProvider IQueryable.Provider
        {
            get { return new TestDbAsyncQueryProvider(this); }
        }
    }


    internal class TestDbAsyncEnumerator : IDbAsyncEnumerator
    {
        private readonly IEnumerator _inner;


        public TestDbAsyncEnumerator(IEnumerator inner)
        {
            _inner = inner;
        }


        public void Dispose()
        {
            _inner.Dispose();
        }


        public Task MoveNextAsync(CancellationToken cancellationToken)
        {
            return Task.FromResult(_inner.MoveNext());
        }


        public T Current
        {
            get { return _inner.Current; }
        }


        object IDbAsyncEnumerator.Current
        {
            get { return Current; }
        }
    }
Copy after login


Usage example:

[TestMethod]
        public void TestMethod1()
        {
            var mockSet = new Mock>();
            var mockContext = new Mock();
            mockContext.Setup(m => m.BLACKLISTED_TICKET).Returns(new TestDbSet());


            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);
        }
Copy after login

If a stored procedure is used, an additional interface for the stored procedure needs to be defined.
For example:

IStorePro {
...
}


StorePro : IStorePro{
...
}


StoreProFake: IStorePro{


}
Copy after login

Then IDataContext is responsible for returning the instance of the stored procedure

IDataContext{
	...
	IStorePro GetStorePro();
	...
}
Copy after login

The above is the content of C# decoupling EntityFramework for unit testing. For more related information, please Follow the PHP Chinese website (www.php.cn)!


Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!