Mocking Database transactions?

mock dbcontext database
c# mock database for unit testing
mock system data entity database
dbcontexttransaction
c# mock framework
mock msdn
how to test transaction rollbacks
testdb iasyncenumerable

I have a pair of tables with a parent/child relationship - incident and incidentDetails. I have a viewmodel that contains information from both of these tables. And I have a business layer method that is passed an instance of the viewmodel that needs to update both tables.

So, in the method, I'm using EF6's new transaction mechanism:

using (var transaction = this.db.Database.BeginTransaction())
{
    try
    {
        // various database stuff
        this.db.SaveChanges();
        // more database stuff
        this.db.SaveChanges();
        // yet more database stuff
        this.db.SaveChanges();

        transaction.Commit();
    }
    catch (Exception ex)
    {
        transaction.Rollback();
        this.logger.logException(ex, "Exception caught in transaction, rolling back");
        throw;
    }
}

And so, my problem. How do I test this?

I'm using Microsoft's unit testing framework, with Moq, and I have had no trouble with mocking up DBContexts, and DbSet<>s, but I can't seem to figure out how to get around the transaction stuff.

If I don't attempt to mock the transaction, I get an InvalidOperationException:

"No connecting string named xxx could be found in the application config file."

Which makes perfect sense - there isn't an application config file, and there isn't any database.

But if I try to mock BeginTransaction(), I get initialization errors: NotSupportedException:

"Invalid setup on a non-virtual member: m => m.Database.BeginTransaction".

And that got me chasing into the weeds, looking at decompiles of the .NET methods, trying to identify some class that might derive from a usable interface, or something, where I could somehow inject a mocking object.

I'm not trying to unit-test MS's transactional code - I just want to make sure that the appropriate changes are made to the appropriate records in each of the tables. But as it sits, it looks like this is non-testable, and that any method that uses transactions is non-testable. And that's just a pain.

I've Googled around, and not found anything of use. Has anyone run into this issue? Anyone have ideas on how to proceed?

Testing this kind of stuff is always complicated, but first of all you should ask yourself if you want to unit test your business logic or if you want to integration test your application.

If you want to unit test your logic, you basically shouldn't even try to mock entity framework, because you do not want to test EF, you just want to test your code, right? To do so, mock any data access object and only unit test your business logic.

But if you want to test if your data access layer works, e.g. if your code can handle all the CRUD operations you have implemented, you should do integration tests against a real database. Do not try to mock any data access objects (EF) in this case, simply run you tests against a test database or a sql-express localDB for example.

[SOLVED], Testing this kind of stuff is always complicated, but first of all you should ask yourself if you want to unit test your business logic or if you want to� "Invalid setup on a non-virtual member: m => m.Database.BeginTransaction". And that got me chasing into the weeds, looking at decompiles of the .NET methods, trying to identify some class that might derive from a usable interface, or something, where I could somehow inject a mocking object.

You can wrap the context and the transaction in an Interface and then implement the interface by some provider class:

public interface IDbContextProvider
{
    YourContext Context { get; set; }
    DbContextTransaction DbTransaction { get; set; }
    void Commit();
    void Rollback();
    void BeginTransaction();
    void SaveChanges();
}

and then implement it:

public class EfContextProvider : IDbContextProvider
{
    public EfContextProvider(YourContext context)
    {
        Context = context;
    }
    public YourContext Context { set; get; }
    public DbContextTransaction DbTransaction { set; get; }

    public void Commit()
    {
        DbTransaction.Commit();
    }

    public void Rollback()
    {
        DbTransaction.Rollback();
    }

    public void BeginTransaction()
    {
        DbTransaction=Context.Database.BeginTransaction();
    }

    public void SaveChanges()
    {
        Context.SaveChanges();
    }
}

so now give your class the IDbContextProvider dependency and work with it (It has also the context inside) . Maybe substitute the using block with _contextProvider.BeginTransaction(); and then also _contextProvider.Commit(); or _contextProvider.Rollback();

Mocking EF DbContext and DbContextTransaction with Proxy , Database.BeginTransaction() in your context, you can't mock it. which controls DbContextTransaction(Ef transaction class)</returns> public� Mocking Database transactions? (4) I have a pair of tables with a parent/child relationship - incident and incidentDetails. I have a viewmodel that contains information from both of these tables. And I have a business layer method that is passed an instance of the viewmodel that needs to update both tables.

I have spent few hours trying to figure it out, I believed it can be done by MS Fakes directly without wrapper or new classe.

You need to do three steps:

  1. Create shim object for DbContextTransaction, and detour its Commit and Rollback methods to do nothing.
  2. Create shim object for Database. And detour its BeginTransaction method to return DbContextTransaction shim object created in step 1.
  3. Detour DbContext.Database property for all instances to return Database shim object created in step 2.

And that all.

    static void SetupDBTransaction()
    {
        System.Data.Entity.Fakes.ShimDbContextTransaction transaction = new System.Data.Entity.Fakes.ShimDbContextTransaction();
        transaction.Commit = () => { };
        transaction.Rollback = () => { };

        System.Data.Entity.Fakes.ShimDatabase database = new System.Data.Entity.Fakes.ShimDatabase();
        database.BeginTransactionIsolationLevel = (isolationLevel) =>{return transaction.Instance;};

        System.Data.Entity.Fakes.ShimDbContext.AllInstances.DatabaseGet = (@this) => { return database.Instance; };
    }

Using Transactions for Unit Tests, Mocking the database by providing a mock implementation of the database access layer is a huge task. It is too huge to be worth the effort. It seems like a recommended way to use most things (database object, transactions, table objects) is global singletons, which cannot be easily mocked. Also entity classes are tightly coupled to the table singletons, making it hard to convert table to non-singleton and also making it hard to create dummy entity objects with fake data.

You can represent your EF classes as POCO classes and isolate all database interactions in database adapter classes. Those adapter classes would have an interface you could mock when testing business logic.

The database operations in the adapter classes can be tested with a real database connection, but with a dedicated database and connection string for the unit tests.

So how about testing business code wrapped in transactions?

In order to isolate the business code from the database adapters, you would have to create an interface for the EF transaction scope that you can mock.

I have previously worked with a design like this, though not with EF, but with similar POCO wrapping (in pseudo C#, not syntax or sanity checked):

interface IDatabaseAdapter 
{
    ITransactionScope CreateTransactionScope();
}

interface ITransactionScope : IDisposable
{
    void Commit();
    void Rollback();        
}

class EntityFrameworkTransactionScope : ITransactionScope
{
    private DbContextTransaction entityTransaction;
    EntityFrameworkTransactionScope(DbContextTransaction entityTransaction)
    {
        this.entityTransaction = entityTransaction;
    }

    public Commit() { entityTransaction.Commit(); }
    public Rollback() { entityTransaction.Rollback(); }
    public Dispose() { entityTransaction.Dispose(); }

}

class EntityFrameworkAdapterBase : IDatabaseAdapter
{
   private Database database;
   protected EntityFrameworkAdapterBase(Database database)
   {
       this.database = database;
   }

   public ITransactionScope CreateTransactionScope()
   {
       return new EntityFrameworkTransactionScope(database.BeginTransaction());
   }
}

interface IIncidentDatabaseAdapter : IDatabaseAdapter
{
    SaveIncident(Incident incident);
}

public EntityIncidentDatabaseAdapter : EntityFrameworkAdapterBase, IIncidentDatabaseAdapter
{
    EntityIncidentDatabaseAdapter(Database database) : base(database) {}

    SaveIncident(Incident incident)
    {
         // code for saving the incident
    }
}

The above design should allow you to create unit test for entity framework operations without worrying about business logic or transaction and to create unit tests for business logic where you can mock database failures and use MOQ or similar to check that rollback is in fact called on your ITransactionScope mock. With something like the above you should be able to cover pretty much any transaction failure at any stage in the business logic that you can think of.

Of course you should supplement your unit tests with some good integration tests, since transactions can be tricky, especially tricky deadlocks can occur when used concurrently and those would be hard to catch in a mocked test.

Creating mock database connections, Using transactions in custom SQL operations 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� In my demonstration of the Dependency Injection design pattern, I manually created a mock object.This let me perform unit tests without needing to access a database. Here is how you can use the Moq library, to eliminate writing the code for manual mock classes.

We implemented ivaylo-pashov's solution along with this code:

//Dependency Injection
public static void RegisterTypes(IUnityContainer container)
        {
            // Register manager mappings.
            container.RegisterType<IDatabaseContextProvider, EntityContextProvider>(new PerResolveLifetimeManager());
        }
    }

//Test Setup
        /// <summary>
        ///     Mocked <see cref="IrdEntities" /> context to be used in testing.
        /// </summary>
        private Mock<CCMSEntities> _irdContextMock;
        /// <summary>
        ///     Mocked <see cref="IDatabaseContextProvider" /> context to be used in testing.
        /// </summary>
        private Mock<IDatabaseContextProvider> _EntityContextProvider;
...

            _irdContextMock = new Mock<CCMSEntities>();
            _irdContextMock.Setup(m => m.Outbreaks).Returns(new Mock<DbSet<Outbreak>>().SetupData(_outbreakData).Object);
            _irdContextMock.Setup(m => m.FDI_Number_Counter).Returns(new Mock<DbSet<FDI_Number_Counter>>().SetupData(new List<FDI_Number_Counter>()).Object);

            _EntityContextProvider = new Mock<IDatabaseContextProvider>();
            _EntityContextProvider.Setup(m => m.Context).Returns(_irdContextMock.Object);

            _irdOutbreakRepository = new IrdOutbreakRepository(_EntityContextProvider.Object, _loggerMock.Object);

// Usage in the Class being tested:
//Constructor
        public IrdOutbreakRepository(IDatabaseContextProvider entityContextProvider, ILogger logger)
        {
            _entityContextProvider = entityContextProvider;
            _irdContext = entityContextProvider.Context;
            _logger = logger;
        }

        /// <summary>
        ///     The wrapper for the Entity Framework context and transaction.
        /// </summary>
        private readonly IDatabaseContextProvider _entityContextProvider;

        // The usage of a transaction that automatically gets mocked because the return type is void.
        _entityContextProvider.BeginTransaction();
...

Transactions and Testing, By mocking the data access layer we can test this functionality without hitting the database. API Layer�. This is our public API which in this sample application is� Which accesses our database inside that method using a passed connection string. Is it possible to setup a mock DB using Moq and create a connection string which points to the mocked DB? I've trying doing something along the lines of. var mockSqlConnnection = new Mock<SqlConnection>();

Mocking IDBContextTransaction for unit tests � Issue #20129 � dotnet , Unit testing your data access. When databases are involved, people will probably quickly jump to writing integration tests, because all they have� Stubbing / mocking a database in .Net. Ask Question Asked 9 years, 3 months ago. Active 8 months ago. Viewed 38k times 33. 13. I have a webservice which basically

Easy Mocking of Your Database, It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have� Database Transactions You may use the transaction method on the DB facade to run a set of operations within a database transaction. If an exception is thrown within the transaction Closure , the transaction will automatically be rolled back.

JDBC mocking for unit testing, This tutorial explains how to test Java code that uses a database without polluting the database with test data. Mock UsersContext by using one of mocking frameworks – in this case Moq. Of course it is hard to say which option is better. In case of first one you can prepare environment that will suite better to our test environment. But on the other hand you will need to spend some time for writing it and later you will need to maintain this code.

Comments
  • stackoverflow.com/questions/32554029/…
  • The problem is that this one method needs to make a series of database calls, in a single transaction. What I want to test is to see that the appropriate calls are made. I'm willing to assume that when I insert or update a record, that the appropriate changes are made to the database. What I am not willing to assume is that when I call the method, the correct series of insert or updates are made.
  • @JeffDege, what you describe is an integration test, not a unit test. A unit test is something that shouldn't depend on any databases. Write an integration test for this stuff.
  • If I was talking to a database, yes, it would be an integration test. That's why I'm trying to mock the database.
  • I'm beginning to understand that EF is not mock friendly. But I strongly disagree that there is a good reason for that.
  • I agree 100% with Jeff here. I run a sproc inside a transaction then I do business logic with an out parameter of a stored proc. I need to test that business logic but I can't because of how transactions are setup in EF? That's garbage.
  • Should this be made to implement IDisposable so that it can be wrapped in a Using statement when used to ensure the DbContextTransaction is disposed?
  • What exactly is the question?
  • What I've been doing, lately, is creating a Local(db) database, within the project.
  • The question is about how to unit test code that use transactions in Entity Framework. The context class can be mocked easily, but not the transactions or the database.
  • @Kaboo, this is excellent, but I'm having issues getting System.Data.Entity.Fakes.ShimDatabase. It should be as simple as right click the System.Data.Entity reference and "add fakes", correct?
  • Doh, right click EntityFramework reference, add fakes.