| File: EFMigrationCommandsTests.cs | Web Access |
| Project: src\tests\Aspire.Hosting.EntityFrameworkCore.Tests\Aspire.Hosting.EntityFrameworkCore.Tests.csproj (Aspire.Hosting.EntityFrameworkCore.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Utils; using Microsoft.Extensions.DependencyInjection; namespace Aspire.Hosting.EntityFrameworkCore.Tests; public class EFMigrationCommandsTests { [Fact] public void AddEFMigrationsAddsUpdateDatabaseCommand() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); // Commands are added to the migration resource var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); var updateCommand = commands.FirstOrDefault(c => c.Name.Contains("ef-database-update")); Assert.NotNull(updateCommand); Assert.Contains("Update Database", updateCommand.DisplayName); } [Fact] public void AddEFMigrationsAddsDropDatabaseCommand() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); var dropCommand = commands.FirstOrDefault(c => c.Name.Contains("ef-database-drop")); Assert.NotNull(dropCommand); Assert.Contains("Drop Database", dropCommand.DisplayName); Assert.NotNull(dropCommand.ConfirmationMessage); } [Fact] public void AddEFMigrationsAddsResetDatabaseCommand() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); var resetCommand = commands.FirstOrDefault(c => c.Name.Contains("ef-database-reset")); Assert.NotNull(resetCommand); Assert.Contains("Reset Database", resetCommand.DisplayName); Assert.NotNull(resetCommand.ConfirmationMessage); } [Fact] public void AddEFMigrationsAddsAddMigrationCommand() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); var addCommand = commands.FirstOrDefault(c => c.Name.Contains("ef-migrations-add")); Assert.NotNull(addCommand); Assert.Contains("Add Migration", addCommand.DisplayName); var nameArgument = Assert.Single(addCommand.Arguments); Assert.Equal("name", nameArgument.Name); Assert.True(nameArgument.Required); } [Fact] public void AddEFMigrationsAddsRemoveMigrationCommand() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); var removeCommand = commands.FirstOrDefault(c => c.Name.Contains("ef-migrations-remove")); Assert.NotNull(removeCommand); Assert.Contains("Remove Migration", removeCommand.DisplayName); } [Fact] public void AddEFMigrationsAddsGetDatabaseStatusCommand() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); var statusCommand = commands.FirstOrDefault(c => c.Name.Contains("ef-database-status")); Assert.NotNull(statusCommand); Assert.Contains("Get Database Status", statusCommand.DisplayName); } [Fact] public void AddEFMigrationsAddsSixCommands() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); // Should have 6 EF-related commands var efCommands = commands.Where(c => c.Name.Contains("ef-")).ToList(); Assert.Equal(6, efCommands.Count); } [Fact] public void AddEFMigrationsWithoutContextAddsCommandsWithoutContextSuffix() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations"); var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); var updateCommand = commands.FirstOrDefault(c => c.Name == "ef-database-update"); Assert.NotNull(updateCommand); Assert.Equal("Update Database", updateCommand.DisplayName); } [Fact] public void AddEFMigrationsWithContextUsesContextTypeName() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); // Verify the context type name is stored on the resource Assert.Equal(typeof(TestDbContext).FullName, migrations.Resource.DbContextTypeName); } [Fact] public void CommandsHaveIcons() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); foreach (var command in commands.Where(c => c.Name.Contains("ef-"))) { Assert.NotNull(command.IconName); } } [Fact] public void DestructiveCommandsHaveConfirmationMessages() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); var dropCommand = commands.First(c => c.Name.Contains("ef-database-drop")); var resetCommand = commands.First(c => c.Name.Contains("ef-database-reset")); Assert.NotNull(dropCommand.ConfirmationMessage); Assert.NotNull(resetCommand.ConfirmationMessage); } [Fact] public void NonDestructiveCommandsDoNotHaveConfirmationMessages() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); var updateCommand = commands.First(c => c.Name.Contains("ef-database-update")); var statusCommand = commands.First(c => c.Name.Contains("ef-database-status")); Assert.Null(updateCommand.ConfirmationMessage); Assert.Null(statusCommand.ConfirmationMessage); } [Fact] public void CommandsAreEnabledWhenNotExecuting() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); var snapshot = new CustomResourceSnapshot { ResourceType = "EFMigration", Properties = [], State = new ResourceStateSnapshot(KnownResourceStates.Finished, KnownResourceStateStyles.Info) }; foreach (var command in commands.Where(c => c.Name.Contains("ef-"))) { var state = command.UpdateState(new UpdateCommandStateContext { ResourceSnapshot = snapshot, Services = builder.Services.BuildServiceProvider() }); Assert.Equal(ResourceCommandState.Enabled, state); } } [Fact] public void CommandsAreDisabledWhenExecutingCommand() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); // Simulate a command currently executing migrations.Resource.IsExecutingCommand = true; var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); var snapshot = new CustomResourceSnapshot { ResourceType = "EFMigration", Properties = [], State = new ResourceStateSnapshot(KnownResourceStates.Running, KnownResourceStateStyles.Info) }; foreach (var command in commands.Where(c => c.Name.Contains("ef-"))) { var state = command.UpdateState(new UpdateCommandStateContext { ResourceSnapshot = snapshot, Services = builder.Services.BuildServiceProvider() }); Assert.Equal(ResourceCommandState.Disabled, state); } } [Fact] public void CommandsAreReenabledAfterCommandCompletes() { using var builder = TestDistributedApplicationBuilder.Create(); var project = builder.AddProject<Projects.ServiceA>("myproject"); var migrations = project.AddEFMigrations("mymigrations", typeof(TestDbContext).FullName!); // Simulate command executing then completing migrations.Resource.IsExecutingCommand = true; var commands = migrations.Resource.Annotations.OfType<ResourceCommandAnnotation>().ToList(); var snapshot = new CustomResourceSnapshot { ResourceType = "EFMigration", Properties = [], State = new ResourceStateSnapshot(KnownResourceStates.Running, KnownResourceStateStyles.Info) }; // Should be disabled while executing foreach (var command in commands.Where(c => c.Name.Contains("ef-"))) { var state = command.UpdateState(new UpdateCommandStateContext { ResourceSnapshot = snapshot, Services = builder.Services.BuildServiceProvider() }); Assert.Equal(ResourceCommandState.Disabled, state); } // Simulate command completed migrations.Resource.IsExecutingCommand = false; snapshot = new CustomResourceSnapshot { ResourceType = "EFMigration", Properties = [], State = new ResourceStateSnapshot(KnownResourceStates.Finished, KnownResourceStateStyles.Info) }; // Should be enabled again foreach (var command in commands.Where(c => c.Name.Contains("ef-"))) { var state = command.UpdateState(new UpdateCommandStateContext { ResourceSnapshot = snapshot, Services = builder.Services.BuildServiceProvider() }); Assert.Equal(ResourceCommandState.Enabled, state); } } // Test classes for DbContext types private sealed class TestDbContext { } }