Search icon
Subscription
0
Cart icon
Close icon
You have no products in your basket yet
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Entity Framework Core Cookbook - Second Edition

You're reading from  Entity Framework Core Cookbook - Second Edition

Product type Book
Published in Nov 2016
Publisher Packt
ISBN-13 9781785883309
Pages 324 pages
Edition 2nd Edition
Languages
Author (1):
Ricardo Peres Ricardo Peres
Profile icon Ricardo Peres

Table of Contents (15) Chapters

Entity Framework Core Cookbook - Second Edition
Credits
About the Author
About the Reviewer
www.PacktPub.com
Preface
1. Improving Entity Framework in the Real World 2. Mapping Entities 3. Validation and Changes 4. Transactions and Concurrency Control 5. Querying 6. Advanced Scenarios 7. Performance and Scalability Pitfalls Index

Creating mock database connections


When working with Entity Framework in a test-driven manner, we need to be able to slip a layer between our last line of code and the framework. This allows us to simulate the database connection without actually hitting the database.

We will be using the NuGet Package Manager to install the Entity Framework Core 1 package, Microsoft.EntityFrameworkCore. We will also be using a SQL Server database for storing the data, so we will also need Microsoft.EntityFrameworkCore.SqlServer.

To mock interfaces and base classes, we will use Moq.

Finally, xunit is the package we will be using for the unit tests and dotnet-text-xunit adds tooling support for Visual Studio. Note that the UnitTests project is a .NET Core App 1.0 (netcoreapp1.0), that Microsoft.EntityFrameworkCore.Design is configured as a build dependency, and Microsoft.EntityFrameworkCore.Tools is set as a tool.

Open Using EF Core Solution from the included source code examples.

Execute the database setup script from the code samples included for this recipe. This can be found in the DataAccess project within the Database folder.

How to do it…

  1. In the DataAccess project, add a new C# interface named IDbContext using the following code:

    using System.Linq;
    namespace DataAccess
    {
        public interface IDbContext
        {
            IQueryable<T> Set<T>() where T : class;
        }
    }
  2. Add a new unit test in the UnitTests project to test so we can supply dummy results for fake database calls with the following code:

    using System.Linq;
    using DataAccess;
    using BusinessLogic;
    using Moq;
    using Xunit;
    namespace UnitTests
    {
        public class MockTest : BaseTest
        {      
            [Fact]
            public void CanMock()
            {
               //Arrange
                var data = new[] { new Blog { Id = 1, Title = "Title" }, newBlog { Id = 2, Title = "No Title" } }.AsQueryable();
                var mock = new Mock<IDbContext>();
                mock.Setup(x => x.Set<Blog>()).Returns(data);
                //Act
                var context = mock.Object;
                var blogs = context.Set<Blog>();
                //Assert
                Assert.Equal(data, blogs);
            }
        }
    }
  3. In the DataAccess project, update the C# class named BlogContext with the following code:

    using BusinessLogic;
    using System.Linq;
    using Microsoft.EntityFrameworkCore;
    namespace DataAccess
    {
        public class BlogContext : DbContext, IDbContext
        {
            private readonly string _connectionString;
            public BlogContext(string connectionString)
            {
                _connectionString = connectionString;
            }
            public DbSet<Blog> Blogs { get; set; }
            IQueryable<T> IDbContext.Set<T>()
            {
                return base.Set<T>();  
            }
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                optionsBuilder.UseSqlServer(_connectionString);
                base.OnConfiguring(optionsBuilder);
            }
            public void Rollback()
            {
                ChangeTracker.Entries().ToList().ForEach(x =>
                {
                    x.State = EntityState.Detached;
                    var keys = GetEntityKey(x.Entity);
                    Set(x.Entity.GetType(), keys);
                });
            }
        }
    }

How it works…

We implemented a fake class —a mock—that mimics some of the functionality of our IDbContext interface that we wish to expose and make testable; in this case, it is just the retrieval of data. This allows us to keep our tests independent of the actual data in the database. Now that we have data available from our mock, we can test whether it acts exactly like we coded it to. Knowing the inputs of the data access code, we can test the outputs for validity. We made our existing BlogContext class implement the interface where we define the contract that we wish to mock, IDbContext, and we configured a mock class to return dummy data whenever its Set method was called.

This layering is accomplished by having a Set method as an abstraction between the public framework method of Set<T> and our code, so we can change the type to something constructible. By layering this method, we can now control every return from the database in the test scenarios.

This layering also provides a better separation of concerns, as the DbSet<T> in Entity Framework mingles multiple independent concerns, such as connection management and querying, into a single object, whereas IQueryable<T> is the standard .NET interface for performing queries against a data source (DbSet<T> implements IQueryable<T>). We will continue to separate these concerns in future recipes.

See also

In this chapter:

  • Unit testing and mocking

You have been reading a chapter from
Entity Framework Core Cookbook - Second Edition
Published in: Nov 2016 Publisher: Packt ISBN-13: 9781785883309
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime}