I want to create a unit test to ensure no developer will commit model changes without the corresponding migration.
How do I test that the database matches the DbContext?
By default, the migrations assembly is the assembly containing the DbContext. Change your target project to the migrations project by using the Package Manager Console's Default project drop-down list, or by executing "dotnet ef" from the directory containing the migrations project.
You can do this by running the Enable-Migrations command in Package Manager Console. This command will create a folder in your solution called Migrations, and put a single class inside it called Configuration.
EF and EF Core DbContext types implement IDisposable . As such, best practice programming suggests that you should wrap them in a using() block (or new C# 8 using statement). Unfortunately, doing this, at least in web apps, is generally a bad idea.
You can leverage some of the lower-level Migrations components to do that:
var migrationsAssembly = db.GetService<IMigrationsAssembly>();
var differ = db.GetService<IMigrationsModelDiffer>();
var hasDifferences = differ.HasDifferences(
migrationsAssembly.ModelSnapshot.Model,
db.Model);
Assert.False(hasDifferences, "You forgot to add a migration!");
Based on @bricelam's answer I created a generic method to test for applied migrations.
private static void ShouldMatchContext<T>()
where T : DbContext
{
using (var connection = new SqliteConnection("DataSource=:memory:"))
{
connection.Open();
var builder = new DbContextOptionsBuilder<T>();
var db = Activator.CreateInstance(typeof(T), builder.UseSqlite(connection).Options) as T;
db.Database.EnsureCreated();
var migrationsAssembly = db.GetService<IMigrationsAssembly>();
var differ = db.GetService<IMigrationsModelDiffer>();
bool hasDifferences = differ.HasDifferences(migrationsAssembly.ModelSnapshot?.Model, db.Model);
Assert.False(hasDifferences);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With