Skip to content

Commit 28b2191

Browse files
committed
Add migration tests
1 parent 52cb475 commit 28b2191

1 file changed

Lines changed: 102 additions & 4 deletions

File tree

‎tests/SQLiteDbMigrationTests.cs‎

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -411,14 +411,95 @@ title TEXT NOT NULL
411411
Assert.AreEqual("0001_CreateMovies", GetAppliedMigrationId(connection, 1));
412412
}
413413

414+
[TestMethod]
415+
public void Migrate_ExistingDbContextCommit_PersistsMigrationsAndHistory()
416+
{
417+
const string version = "1.2.3";
418+
419+
var migration = new DelegateMigration("0001_CreateMovies", static context => context.ExecuteNonQuery(
420+
"""
421+
CREATE TABLE movies (
422+
id INTEGER PRIMARY KEY NOT NULL,
423+
title TEXT NOT NULL
424+
);
425+
"""));
426+
427+
SQLiteDbMigration[] migrations =
428+
[
429+
migration
430+
];
431+
432+
using (var connection = CreateConnection())
433+
{
434+
connection.AcquireLock(() =>
435+
{
436+
using var dbContext = new SQLiteDbContext(connection);
437+
438+
migrations.Migrate(dbContext, version, CancellationToken.None);
439+
440+
Assert.IsTrue(connection.TableExists("movies", CancellationToken.None));
441+
Assert.IsTrue(connection.TableExists("__nuext_migrations", CancellationToken.None));
442+
443+
dbContext.Commit();
444+
}, CancellationToken.None);
445+
}
446+
447+
Assert.AreEqual(1, migration.ExecutionCount);
448+
449+
using var verificationConnection = CreateConnection();
450+
Assert.IsTrue(verificationConnection.TableExists("movies", CancellationToken.None));
451+
Assert.IsTrue(verificationConnection.TableExists("__nuext_migrations", CancellationToken.None));
452+
Assert.AreEqual(1L, GetAppliedMigrationCount(verificationConnection));
453+
Assert.AreEqual("0001_CreateMovies", GetAppliedMigrationId(verificationConnection, 1));
454+
Assert.AreEqual(version, GetAppliedMigrationVersion(verificationConnection, 1));
455+
}
456+
457+
[TestMethod]
458+
public void Migrate_ExistingDbContextRollback_RollsBackMigrationsAndHistory()
459+
{
460+
var migration = new DelegateMigration("0001_CreateMovies", static context => context.ExecuteNonQuery(
461+
"""
462+
CREATE TABLE movies (
463+
id INTEGER PRIMARY KEY NOT NULL,
464+
title TEXT NOT NULL
465+
);
466+
"""));
467+
468+
SQLiteDbMigration[] migrations =
469+
[
470+
migration
471+
];
472+
473+
using (var connection = CreateConnection())
474+
{
475+
connection.AcquireLock(() =>
476+
{
477+
using var dbContext = new SQLiteDbContext(connection);
478+
479+
migrations.Migrate(dbContext, CancellationToken.None);
480+
481+
Assert.IsTrue(connection.TableExists("movies", CancellationToken.None));
482+
Assert.IsTrue(connection.TableExists("__nuext_migrations", CancellationToken.None));
483+
484+
dbContext.Rollback();
485+
}, CancellationToken.None);
486+
}
487+
488+
Assert.AreEqual(1, migration.ExecutionCount);
489+
490+
using var verificationConnection = CreateConnection();
491+
Assert.IsFalse(verificationConnection.TableExists("movies", CancellationToken.None));
492+
Assert.IsFalse(verificationConnection.TableExists("__nuext_migrations", CancellationToken.None));
493+
}
494+
414495
private SQLiteDbConnection CreateConnection()
415496
{
416497
return new SQLiteDbConnection(_connectionString);
417498
}
418499

419500
private static long GetAppliedMigrationCount(SQLiteDbConnection connection)
420501
{
421-
object? result = connection.ExecuteScalar("SELECT COUNT(*) FROM __nuext_migrations;");
502+
object? result = connection.ExecuteScalar("SELECT COUNT(*) FROM __nuext_migrations;", CommandBehavior.Default, CancellationToken.None);
422503
Assert.IsNotNull(result);
423504
return Convert.ToInt64(result);
424505
}
@@ -438,22 +519,24 @@ private static void CreateMigrationHistory(SQLiteDbConnection connection)
438519
CREATE TABLE __nuext_migrations (
439520
sequence INTEGER PRIMARY KEY,
440521
migration_id TEXT NOT NULL UNIQUE CHECK(migration_id <> ''),
522+
version TEXT,
441523
applied_at INTEGER NOT NULL
442524
);
443525
""");
444526
}
445527

446-
private static void AddAppliedMigration(SQLiteDbConnection connection, string migrationId, long sequence)
528+
private static void AddAppliedMigration(SQLiteDbConnection connection, string migrationId, long sequence, string? version = null)
447529
{
448530
connection.ExecuteNonQuery(
449531
"""
450-
INSERT INTO __nuext_migrations (sequence, migration_id, applied_at)
451-
VALUES (@sequence, @migration_id, @applied_at);
532+
INSERT INTO __nuext_migrations (sequence, migration_id, version, applied_at)
533+
VALUES (@sequence, @migration_id, @version, @applied_at);
452534
""",
453535
CommandBehavior.Default,
454536
default,
455537
DbType.Int64.CreateInputParam("@sequence", sequence),
456538
DbType.String.CreateInputParam("@migration_id", migrationId),
539+
DbType.String.CreateInputParam("@version", version),
457540
DbType.Int64.CreateInputParam("@applied_at", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()));
458541
}
459542

@@ -473,6 +556,21 @@ FROM __nuext_migrations
473556
return Convert.ToString(result)!;
474557
}
475558

559+
private static string? GetAppliedMigrationVersion(SQLiteDbConnection connection, long sequence)
560+
{
561+
object? result = connection.ExecuteScalar(
562+
"""
563+
SELECT version
564+
FROM __nuext_migrations
565+
WHERE sequence = @sequence;
566+
""",
567+
CommandBehavior.Default,
568+
default,
569+
DbType.Int64.CreateInputParam("@sequence", sequence));
570+
571+
return result is null or DBNull ? null : Convert.ToString(result);
572+
}
573+
476574
private sealed class DelegateMigration : SQLiteDbMigration
477575
{
478576
private readonly Action<SQLiteDbMigrationContext> _up;

0 commit comments

Comments
 (0)