EfCore.TestSupport

repository·main·Indexed 18 days ago

https://github.com/jonpsmith/efcore.testsupport

A utility library for simplifying unit testing in applications using Entity Framework Core. It provides helpers for managing test databases (SQL Server, PostgreSQL, Cosmos DB, and in-memory SQLite), handling connection strings, resetting schemas via EnsureClean, capturing logs, and applying SQL scripts.

Tokens
2K
Snippets
2
Records
13
Agent score
63%

What's inside EfCore.TestSupport

  1. Overview of EfCore.TestSupport tool groups

    main

    The library is organized into several functional groups to assist with different testing scenarios:

    1. In-memory SQLite: Helpers to create an in-memory Sqlite database for unit testing (works with most providers with limitations).
    2. Connection Strings: Helpers to create connection strings with unique database names.
    3. SQL Server: Helpers to create unique SQL Server databases for unit testing.
    4. Cosmos DB: Helpers to create Cosmos DB options linked to the Azure Cosmos DB Emulator.
    5. Database Reset: Helpers for wiping all data and resetting the schema on a SQL Server database.
    6. Test Data: Tools for retrieving test data or file paths to test data.
    7. SQL Scripts: A tool for applying a SQL script file to an EF Core database.
    8. Logging: Tools for capturing EF Core logging.
  2. Migrate from version 5.1.0 to 5.2.0 (PostgreSQL)

    main
    When upgrading from 5.1.0 to 5.2.0, CreatePostgreSqlUniqueDatabaseOptions has been renamed to CreatePostgreSqlUniqueClassOptions to maintain consistency with other usages. Additionally, there are extra checks on the length of the PostgreSQL database name due to a 64-character limit.
  3. Fix breaking changes in SqliteInMemory options

    main

    In version 5+, SqliteInMemory.CreateOptions<T> disposes the connection when the context is disposed. If your tests use multiple DbContext instances with the same options, the second instance will find an empty database. Use one of the following four strategies to resolve this:

    1. Quick and Easy: Turn off Dispose

    Use options.TurnOffDispose() to restore the behavior of previous versions where the connection persists.

    2. Best Approach: Single Instance with ChangeTracker.Clear()

    Instead of multiple DbContext instances, use a single instance and call context.ChangeTracker.Clear() to remove tracked entities. This is the recommended approach as it allows for cleaner code using using var context = ....

    3. Keep multiple using blocks: Use StopNextDispose()

    If you must use multiple using blocks, call options.StopNextDispose() immediately after creating the options. This prevents the first DbContext from disposing the underlying connection.

    4. Many DbContext instances: Manual Dispose

    If you have many instances, turn off automatic disposal and call options.ManualDispose() at the very end of your test.

    // Strategy 1: Turn off Dispose
    var options = SqliteInMemory.CreateOptions<BookContext>();
    options.TurnOffDispose();
    
    // Strategy 2: Best approach (Single instance)
    var options = SqliteInMemory.CreateOptions<BookContext>();
    using var context = new BookContext(options);
    context.Database.EnsureCreated();
    context.SeedDatabaseFourBooks();
    context.ChangeTracker.Clear(); // Clears tracked entities so next query hits DB
    var books = context.Books.ToList();
    
    // Strategy 3: Stop next dispose
    var options = SqliteInMemory.CreateOptions<BookContext>();
    options.StopNextDispose();
    using (var context = new BookContext(options)) { /* ... */ }
    using (var context = new BookContext(options)) { /* ... */ }
    
    // Strategy 4: Manual Dispose
    var options = SqliteInMemory.CreateOptions<BookContext>();
    options.TurnOffDispose();
    using (var context = new BookContext(options)) { /* ... */ }
    using (var context = new BookContext(options)) { /* ... */ }
    options.ManualDispose();
  4. Install EfCore.TestSupport via NuGet

    main

    EfCore.TestSupport is a NuGet package providing utilities for testing applications that use Entity Framework Core. It supports SQL Server, PostgreSQL, Cosmos DB, and a generic in-memory SQLite approach.

    To use this library, install the EfCore.TestSupport package from NuGet.

    dotnet add package EfCore.TestSupport
  5. Migrate from version 5.0.0 (Breaking Changes)

    main

    Version 5.0.0 introduced several breaking changes:

    • SqliteInMemory methods now return an IDisposable options object; you must manage its disposal to ensure the connection closes at the end of the test.
    • EfSchemaCompare has been moved to a separate library: EfCore.SchemaCompare.
    • SeedDatabase was removed (users are advised to use version 3.2.0 for this feature).
    • InMemory Database helper was removed; use EF Core's native In-Memory database instead.
  6. Upgrade from EfCore.TestSupport v3.2.0 to v5+

    main

    When upgrading to version 5 or higher, be aware of the following:

    • EF Core Compatibility: EfCore.TestSupport v5 requires EF Core 5.0.1 or higher.
    • Breaking Change: SqliteInMemory.CreateOptions<T> now implements IDisposable. Disposing the DbContext will now also dispose the underlying SQLite connection, which can cause subsequent tests using the same options to fail because the in-memory data is lost.
    • Removed Features:
      • EfSchemaCompare has been moved to a separate library: EfCore.SchemaCompare.
      • The InMemory Database helper has been removed (use EF Core's native In-Memory provider instead).
      • SeedDatabase has been removed.
    • Staying on v3.2.0: If you rely heavily on EfSchemaCompare or SeedDatabase and do not wish to refactor your SQLite tests, you can continue using version 3.2.0. Note that you must load EF Core 5 NuGet packages manually to ensure they take precedence over the versions bundled in the v3.2.0 library.
  7. Use PostgreSQL database helpers

    main
    Starting from version 5.1.0, PostgreSQL database helpers are available, including EnsureClean. Note that in version 6.0.2, FasterPostgreSqlEnsureClean requires a password to be injected. In version 5.2.2, the EnsureClean implementation was updated to use current_user instead of postgres.
  8. Configure SqliteInMemory with logging

    main
    In version 5.0.0 and later, SqliteInMemory includes a CreateOptionsWithLogTo extension method. Note that in version 5.0.0, SqliteInMemory methods were altered to return an IDisposable options object, which disposes of the connection at the end of the test.