5

I'd like to run actual integration tests of my EF4.1 repositories against an in-memory database a la ayende's nhibernate version.

I have a code first model, against a legacy database (old table and column names need mapping to my entites using code configurations).

I'd like to be able to use Sqlite (or other) to:

  1. Generate an in-memory database from my model
  2. Create a DBContext for my model with this in-memory database
  3. I have already in place IoC/DI of a IDBContextFactory which gets constructed with my (Generic) Repositories (also using a GenericRepository pattern)

There's bits and bobs on-line which suggest it should be possible, but not much for code-first approaches. Anyone know if this is possible?

Some snippets of my test library, see // THROWS ERROR marking runtime errors:

public class MyDbContextFactory : IDbContextFactory
  {
    private static object context;
    public object CurrentContext
    {
      get {
        if(context == null)
        {
          // ?? DOESN'T WORK AS THERE'S NO META DATA
          var connBuilder = new EntityConnectionStringBuilder();
          connBuilder.Provider = "System.Data.SQLite";
          connBuilder.Metadata = 
           @"res://*/TestEfDb.csdl|res://*/TestEfDb.ssdl|res://*/TestEfDb.msl";
          connBuilder.ProviderConnectionString = 
           ConfigurationManager.ConnectionStrings["DataContext"].Name;

          var entConnection = new EntityConnection(connBuilder.ConnectionString);

          // THROWS ERROR: sqlite Format of the initialization string does not
          // conform to specification starting at index 0
          // for connection string "Data Source=:memory:;Version=3;New=True;"

          //var entConnection = new EntityConnection
          // (ConfigurationManager.ConnectionStrings["DataContext"].Name);
          context = new MyDbContext(entConnection);
        }
        return context;
      }
    }
  }

...

 [Test]
    public void test_me()
    {
        var auditRespository = new AuditRepository(new MyDbContextFactory());
        auditRespository.GetAll<Audit>();
    }
2
  • Several times you mentioned code first but in the same time you are building entity connection string referencing resource files from EDMX file (designer) so what kind of approach are you using? Commented May 6, 2011 at 13:31
  • quote: "?? DOESNT WORK AS THERES NO META DATA" its code first Commented May 6, 2011 at 13:34

2 Answers 2

9

Use SQL Compact 4.0 (download both SqlCE and tools by web platform installer) - EF Code first has direct support for that. The only difference will be that your application will use connection string to big SQL Server:

<add name="MyDbContext" 
     provider="System.Data.SqlClient" 
     connectionString=
       "Data Source=...;InitialCatalog=...;Integrated Security=SSPI" />

and your tests will use connection string to SQL Compact:

<add name="MyDbContext" 
     provider="System.Data.SqlServerCe.4.0" 
     connectionString="Data Source=Database.sdf" />
Sign up to request clarification or add additional context in comments.

8 Comments

Fantastic. Works a treat. Thanks!
I still don't considder this unit testing, because you will need to do some sort of clean up after each test to keep the database in a consistent state.
@Steven: It is not unit testing. It is integration testing and in my experience the only working approach to really test the code using IQueryable and EF. I will read your linked article later.
@Ladislay: When using any O/RM tool, we need integration tests. At least we need to make sure that the mapping layer is defined correctly and we need integration tests for this. I think we agree on that. But for testing the business logic, it is much more valuable to have unit tests, because they run so much faster and are easier to maintain. But again, we shouldn't bet on unit tests alone.
@Steven: I know this theory and I used it but it didn't work with defining queries in business logic. Once we run did unit tests we worked with linq-to-objects instead of linq-to-entities and tests were green but many times the code didn't work when we run the same queries with EF provider. Linq-to-entities is only subset of linq functionality so I prefer to test queries directly with a real db provider.
|
0

Take a look at this article: Faking your LINQ provider. It describes how you can hide Entity Framework behind an abstraction, so that you can easily unit test your application, while still allowing to use LINQ (over IQueryable) queries against it in your application code.

Note that this does not completely remove the need of writing integration tests, since you would still need to test the database mapping layer and possibly test whether the chosen LINQ provider is able to execute the LINQ queries.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.