diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs index 328f9b661ab..39d3385f2ea 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs @@ -83,9 +83,7 @@ public virtual string TransformText() this.Write(this.ToStringHelper.ToStringWithCulture(entityType.Name)); this.Write("> "); this.Write(this.ToStringHelper.ToStringWithCulture(entityType.GetDbSetName())); - this.Write(" { get; set; }"); - this.Write(this.ToStringHelper.ToStringWithCulture(Options.UseNullableReferenceTypes ? " = null!;" : "")); - this.Write("\r\n\r\n"); + this.Write(" { get; set; }\r\n\r\n"); } diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.tt b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.tt index af05dd8d0dc..e46cd7bbf64 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.tt +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.tt @@ -62,7 +62,7 @@ public partial class <#= Options.ContextName #> : DbContext foreach (var entityType in Model.GetEntityTypes().Where(e => !e.IsSimpleManyToManyJoinEntityType())) { #> - public virtual DbSet<<#= entityType.Name #>> <#= entityType.GetDbSetName() #> { get; set; }<#= Options.UseNullableReferenceTypes ? " = null!;" : "" #> + public virtual DbSet<<#= entityType.Name #>> <#= entityType.GetDbSetName() #> { get; set; } <# } diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs index c2092e43f83..1f7d9345d59 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs @@ -21,8 +21,8 @@ public CSharpDbContextGeneratorTest(ModelCodeGeneratorTestFixture fixture, ITest } [ConditionalFact] - public void Empty_model() - => Test( + public Task Empty_model() + => TestAsync( modelBuilder => { }, new ModelCodeGenerationOptions(), code => @@ -66,8 +66,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) model => Assert.Empty(model.GetEntityTypes())); [ConditionalFact] - public void SuppressConnectionStringWarning_works() - => Test( + public Task SuppressConnectionStringWarning_works() + => TestAsync( modelBuilder => { }, new ModelCodeGenerationOptions { SuppressConnectionStringWarning = true }, code => @@ -108,8 +108,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) model => Assert.Empty(model.GetEntityTypes())); [ConditionalFact] - public void SuppressOnConfiguring_works() - => Test( + public Task SuppressOnConfiguring_works() + => TestAsync( modelBuilder => { }, new ModelCodeGenerationOptions { SuppressOnConfiguring = true }, code => @@ -143,8 +143,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) null); [ConditionalFact] - public void DbSets_without_nrt() - => Test( + public Task DbSets_without_nrt() + => TestAsync( modelBuilder => modelBuilder.Entity("Entity"), new ModelCodeGenerationOptions { @@ -160,8 +160,8 @@ public void DbSets_without_nrt() null); [ConditionalFact] - public void DbSets_with_nrt() - => Test( + public Task DbSets_with_nrt() + => TestAsync( modelBuilder => modelBuilder.Entity("Entity"), new ModelCodeGenerationOptions { @@ -171,7 +171,8 @@ public void DbSets_with_nrt() }, code => { - Assert.Contains("DbSet Entity { get; set; } = null!;", code.ContextFile.Code); + Assert.Contains("DbSet Entity { get; set; }", code.ContextFile.Code); + Assert.DoesNotContain("DbSet Entity { get; set; } = null!;", code.ContextFile.Code); }, null); @@ -231,8 +232,8 @@ public void Plugins_work() } [ConditionalFact] - public void IsRequired_is_generated_for_ref_property_without_nrt() - => Test( + public Task IsRequired_is_generated_for_ref_property_without_nrt() + => TestAsync( modelBuilder => { modelBuilder.Entity( @@ -262,8 +263,8 @@ public void IsRequired_is_generated_for_ref_property_without_nrt() }); [ConditionalFact] - public void IsRequired_is_not_generated_for_ref_property_with_nrt() - => Test( + public Task IsRequired_is_not_generated_for_ref_property_with_nrt() + => TestAsync( modelBuilder => { modelBuilder.Entity( @@ -293,8 +294,8 @@ public void IsRequired_is_not_generated_for_ref_property_with_nrt() }); [ConditionalFact] - public void Comments_use_fluent_api() - => Test( + public Task Comments_use_fluent_api() + => TestAsync( modelBuilder => modelBuilder.Entity( "Entity", x => @@ -312,8 +313,8 @@ public void Comments_use_fluent_api() model.FindEntityType("TestNamespace.Entity").GetProperty("Property").GetComment())); [ConditionalFact] - public void Entity_comments_use_fluent_api() - => Test( + public Task Entity_comments_use_fluent_api() + => TestAsync( modelBuilder => modelBuilder.Entity( "Entity", x => @@ -329,8 +330,8 @@ public void Entity_comments_use_fluent_api() model.FindEntityType("TestNamespace.Entity").GetComment())); [ConditionalFact] - public void Views_work() - => Test( + public Task Views_work() + => TestAsync( modelBuilder => modelBuilder.Entity("Vista").ToView("Vista"), new ModelCodeGenerationOptions { UseDataAnnotations = true }, code => Assert.Contains(".ToView(\"Vista\")", code.ContextFile.Code), @@ -346,7 +347,7 @@ public void Views_work() }); [ConditionalFact] - public void ModelInDifferentNamespaceDbContext_works() + public Task ModelInDifferentNamespaceDbContext_works() { var modelGenerationOptions = new ModelCodeGenerationOptions { @@ -356,7 +357,7 @@ public void ModelInDifferentNamespaceDbContext_works() const string entityInAnotherNamespaceTypeName = "EntityInAnotherNamespace"; - Test( + return TestAsync( modelBuilder => modelBuilder.Entity(entityInAnotherNamespaceTypeName) , modelGenerationOptions , code => Assert.Contains(string.Concat("using ", modelGenerationOptions.ModelNamespace, ";"), code.ContextFile.Code) @@ -365,13 +366,13 @@ public void ModelInDifferentNamespaceDbContext_works() } [ConditionalFact] - public void ModelSameNamespaceDbContext_works() + public Task ModelSameNamespaceDbContext_works() { var modelGenerationOptions = new ModelCodeGenerationOptions { ContextNamespace = "TestNamespace" }; const string entityInAnotherNamespaceTypeName = "EntityInAnotherNamespace"; - Test( + return TestAsync( modelBuilder => modelBuilder.Entity(entityInAnotherNamespaceTypeName) , modelGenerationOptions , code => Assert.DoesNotContain(string.Concat("using ", modelGenerationOptions.ModelNamespace, ";"), code.ContextFile.Code) @@ -380,8 +381,8 @@ public void ModelSameNamespaceDbContext_works() } [ConditionalFact] - public void ValueGenerated_works() - => Test( + public Task ValueGenerated_works() + => TestAsync( modelBuilder => modelBuilder.Entity( "Entity", x => @@ -414,8 +415,8 @@ public void ValueGenerated_works() }); [ConditionalFact] - public void HasPrecision_works() - => Test( + public Task HasPrecision_works() + => TestAsync( modelBuilder => modelBuilder.Entity( "Entity", x => @@ -439,8 +440,8 @@ public void HasPrecision_works() }); [ConditionalFact] - public void Collation_works() - => Test( + public Task Collation_works() + => TestAsync( modelBuilder => modelBuilder.Entity("Entity").Property("UseCollation").UseCollation("Some Collation"), new ModelCodeGenerationOptions(), code => Assert.Contains("Property(e => e.UseCollation).UseCollation(\"Some Collation\")", code.ContextFile.Code), @@ -451,8 +452,8 @@ public void Collation_works() }); [ConditionalFact] - public void ComputedColumnSql_works() - => Test( + public Task ComputedColumnSql_works() + => TestAsync( modelBuilder => modelBuilder.Entity("Entity").Property("ComputedColumn").HasComputedColumnSql("1 + 2"), new ModelCodeGenerationOptions(), code => Assert.Contains(".HasComputedColumnSql(\"1 + 2\")", code.ContextFile.Code), @@ -463,8 +464,8 @@ public void ComputedColumnSql_works() }); [ConditionalFact] - public void IsUnicode_works() - => Test( + public Task IsUnicode_works() + => TestAsync( modelBuilder => { modelBuilder.Entity("Entity").Property("UnicodeColumn").IsUnicode(); @@ -484,8 +485,8 @@ public void IsUnicode_works() }); [ConditionalFact] - public void ComputedColumnSql_works_stored() - => Test( + public Task ComputedColumnSql_works_stored() + => TestAsync( modelBuilder => modelBuilder.Entity("Entity").Property("ComputedColumn") .HasComputedColumnSql("1 + 2", stored: true), new ModelCodeGenerationOptions(), @@ -497,8 +498,8 @@ public void ComputedColumnSql_works_stored() }); [ConditionalFact] - public void ComputedColumnSql_works_unspecified() - => Test( + public Task ComputedColumnSql_works_unspecified() + => TestAsync( modelBuilder => modelBuilder.Entity("Entity").Property("ComputedColumn").HasComputedColumnSql(), new ModelCodeGenerationOptions(), code => Assert.Contains(".HasComputedColumnSql()", code.ContextFile.Code), @@ -509,8 +510,8 @@ public void ComputedColumnSql_works_unspecified() }); [ConditionalFact] - public void DefaultValue_works_unspecified() - => Test( + public Task DefaultValue_works_unspecified() + => TestAsync( modelBuilder => modelBuilder.Entity("Entity").Property("DefaultedColumn").HasDefaultValue(), new ModelCodeGenerationOptions(), code => Assert.Contains(".HasDefaultValue()", code.ContextFile.Code), @@ -521,8 +522,8 @@ public void DefaultValue_works_unspecified() }); [ConditionalFact] - public void DefaultValueSql_works_unspecified() - => Test( + public Task DefaultValueSql_works_unspecified() + => TestAsync( modelBuilder => modelBuilder.Entity("Entity").Property("DefaultedColumn").HasDefaultValueSql(), new ModelCodeGenerationOptions(), code => Assert.Contains(".HasDefaultValueSql()", code.ContextFile.Code), @@ -533,8 +534,8 @@ public void DefaultValueSql_works_unspecified() }); [ConditionalFact] - public void Entity_with_indexes_and_use_data_annotations_false_always_generates_fluent_API() - => Test( + public Task Entity_with_indexes_and_use_data_annotations_false_always_generates_fluent_API() + => TestAsync( modelBuilder => modelBuilder .Entity( "EntityWithIndexes", @@ -608,8 +609,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) Assert.Equal(2, model.FindEntityType("TestNamespace.EntityWithIndexes").GetIndexes().Count())); [ConditionalFact] - public void Entity_with_indexes_and_use_data_annotations_true_generates_fluent_API_only_for_indexes_with_annotations() - => Test( + public Task Entity_with_indexes_and_use_data_annotations_true_generates_fluent_API_only_for_indexes_with_annotations() + => TestAsync( modelBuilder => modelBuilder .Entity( "EntityWithIndexes", @@ -679,8 +680,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) Assert.Equal(2, model.FindEntityType("TestNamespace.EntityWithIndexes").GetIndexes().Count())); [ConditionalFact] - public void Indexes_with_descending() - => Test( + public Task Indexes_with_descending() + => TestAsync( modelBuilder => modelBuilder .Entity( "EntityWithIndexes", @@ -777,8 +778,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) }); [ConditionalFact] - public void Entity_lambda_uses_correct_identifiers() - => Test( + public Task Entity_lambda_uses_correct_identifiers() + => TestAsync( modelBuilder => { modelBuilder.Entity( @@ -862,8 +863,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) model => { }); [ConditionalFact] - public void Column_type_is_not_scaffolded_as_annotation() - => Test( + public Task Column_type_is_not_scaffolded_as_annotation() + => TestAsync( modelBuilder => modelBuilder .Entity( "Employee", @@ -923,8 +924,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) Assert.Equal("date", model.FindEntityType("TestNamespace.Employee").GetProperty("HireDate").GetConfiguredColumnType())); [ConditionalFact] - public void Is_fixed_length_annotation_should_be_scaffolded_without_optional_parameter() - => Test( + public Task Is_fixed_length_annotation_should_be_scaffolded_without_optional_parameter() + => TestAsync( modelBuilder => modelBuilder .Entity( "Employee", @@ -939,8 +940,8 @@ public void Is_fixed_length_annotation_should_be_scaffolded_without_optional_par Assert.Equal(true, model.FindEntityType("TestNamespace.Employee").GetProperty("Name").IsFixedLength())); [ConditionalFact] - public void Global_namespace_works() - => Test( + public Task Global_namespace_works() + => TestAsync( modelBuilder => modelBuilder.Entity("MyEntity"), new ModelCodeGenerationOptions { ModelNamespace = string.Empty }, code => @@ -992,8 +993,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) }); [ConditionalFact] - public void Global_namespace_works_just_context() - => Test( + public Task Global_namespace_works_just_context() + => TestAsync( modelBuilder => modelBuilder.Entity("MyEntity"), new ModelCodeGenerationOptions { ModelNamespace = "TestNamespace", ContextNamespace = string.Empty }, code => @@ -1008,8 +1009,8 @@ public void Global_namespace_works_just_context() }); [ConditionalFact] - public void Global_namespace_works_just_model() - => Test( + public Task Global_namespace_works_just_model() + => TestAsync( modelBuilder => modelBuilder.Entity("MyEntity"), new ModelCodeGenerationOptions { ModelNamespace = string.Empty, ContextNamespace = "TestNamespace" }, code => @@ -1023,8 +1024,8 @@ public void Global_namespace_works_just_model() }); [ConditionalFact] - public void Fluent_calls_in_custom_namespaces_work() - => Test( + public Task Fluent_calls_in_custom_namespaces_work() + => TestAsync( modelBuilder => TestModelBuilderExtensions.TestFluentApiCall(modelBuilder), new ModelCodeGenerationOptions { SuppressOnConfiguring = true }, code => @@ -1062,13 +1063,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) skipBuild: true); [ConditionalFact] - public void Temporal_table_works() + public async Task Temporal_table_works() // Shadow properties. Issue #26007. => Assert.Equal( SqlServerStrings.TemporalPeriodPropertyMustBeInShadowState("Customer", "PeriodStart"), - Assert.Throws( + (await Assert.ThrowsAsync( () => - Test( + TestAsync( modelBuilder => modelBuilder.Entity( "Customer", e => { @@ -1135,11 +1136,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) model => { // TODO - })).Message); + }))).Message); [ConditionalFact] - public void Sequences_work() - => Test( + public Task Sequences_work() + => TestAsync( modelBuilder => modelBuilder.HasSequence("EvenNumbers", "dbo") .StartsAt(2) .IncrementsBy(2) @@ -1169,8 +1170,8 @@ public void Sequences_work() }); [ConditionalFact] - public void Trigger_works() - => Test( + public Task Trigger_works() + => TestAsync( modelBuilder => modelBuilder .Entity( "Employee", @@ -1245,8 +1246,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) }); [ConditionalFact] - public void ValueGenerationStrategy_works_when_none() - => Test( + public Task ValueGenerationStrategy_works_when_none() + => TestAsync( modelBuilder => modelBuilder.Entity( "Channel", x => diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpEntityTypeGeneratorTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpEntityTypeGeneratorTest.cs index f7466dbf537..af4fbd68cc8 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpEntityTypeGeneratorTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpEntityTypeGeneratorTest.cs @@ -16,8 +16,8 @@ public CSharpEntityTypeGeneratorTest(ModelCodeGeneratorTestFixture fixture, ITes } [ConditionalFact] - public void KeylessAttribute_is_generated_for_key_less_entity() - => Test( + public Task KeylessAttribute_is_generated_for_key_less_entity() + => TestAsync( modelBuilder => modelBuilder.Entity("Vista").HasNoKey(), new ModelCodeGenerationOptions { UseDataAnnotations = true }, code => @@ -81,8 +81,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) }); [ConditionalFact] - public void TableAttribute_is_generated_for_custom_name() - => Test( + public Task TableAttribute_is_generated_for_custom_name() + => TestAsync( modelBuilder => { modelBuilder.Entity( @@ -123,8 +123,8 @@ public partial class Vista }); [ConditionalFact] - public void TableAttribute_is_not_generated_for_default_schema() - => Test( + public Task TableAttribute_is_not_generated_for_default_schema() + => TestAsync( modelBuilder => { modelBuilder.HasDefaultSchema("dbo"); @@ -165,8 +165,8 @@ public partial class Vista }); [ConditionalFact] - public void TableAttribute_is_generated_for_non_default_schema() - => Test( + public Task TableAttribute_is_generated_for_non_default_schema() + => TestAsync( modelBuilder => { modelBuilder.HasDefaultSchema("dbo"); @@ -208,8 +208,8 @@ public partial class Vista }); [ConditionalFact] - public void TableAttribute_is_not_generated_for_views() - => Test( + public Task TableAttribute_is_not_generated_for_views() + => TestAsync( modelBuilder => modelBuilder.Entity("Vista").ToView("Vistas", "dbo"), new ModelCodeGenerationOptions { UseDataAnnotations = true }, code => @@ -240,8 +240,8 @@ public partial class Vista }); [ConditionalFact] - public void IndexAttribute_is_generated_for_multiple_indexes_with_name_unique_descending() - => Test( + public Task IndexAttribute_is_generated_for_multiple_indexes_with_name_unique_descending() + => TestAsync( modelBuilder => modelBuilder .Entity( "EntityWithIndexes", @@ -299,8 +299,8 @@ public partial class EntityWithIndexes }); [ConditionalFact] - public void IndexAttribute_is_generated_with_ascending_descending() - => Test( + public Task IndexAttribute_is_generated_with_ascending_descending() + => TestAsync( modelBuilder => modelBuilder .Entity( "EntityWithAscendingDescendingIndexes", @@ -365,8 +365,8 @@ public partial class EntityWithAscendingDescendingIndexes }); [ConditionalFact] - public void Entity_with_indexes_generates_IndexAttribute_only_for_indexes_without_annotations() - => Test( + public Task Entity_with_indexes_generates_IndexAttribute_only_for_indexes_without_annotations() + => TestAsync( modelBuilder => modelBuilder .Entity( "EntityWithIndexes", @@ -456,8 +456,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) Assert.Equal(2, model.FindEntityType("TestNamespace.EntityWithIndexes").GetIndexes().Count())); [ConditionalFact] - public void KeyAttribute_is_generated_for_single_property_and_no_fluent_api() - => Test( + public Task KeyAttribute_is_generated_for_single_property_and_no_fluent_api() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -531,8 +531,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) Assert.Equal("PrimaryKey", model.FindEntityType("TestNamespace.Entity").FindPrimaryKey().Properties[0].Name)); [ConditionalFact] - public void KeyAttribute_is_generated_on_multiple_properties_but_and_uses_PrimaryKeyAttribute_for_composite_key() - => Test( + public Task KeyAttribute_is_generated_on_multiple_properties_but_and_uses_PrimaryKeyAttribute_for_composite_key() + => TestAsync( modelBuilder => modelBuilder .Entity( "Post", @@ -609,8 +609,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) }); [ConditionalFact] - public void Required_and_not_required_properties_without_nrt() - => Test( + public Task Required_and_not_required_properties_without_nrt() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -661,8 +661,8 @@ public partial class Entity }); [ConditionalFact] - public void Required_and_not_required_properties_with_nrt() - => Test( + public Task Required_and_not_required_properties_with_nrt() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -712,8 +712,8 @@ public partial class Entity }); [ConditionalFact] - public void Required_and_not_required_navigations_without_nrt() - => Test( + public Task Required_and_not_required_navigations_without_nrt() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -791,8 +791,8 @@ public partial class Entity }); [ConditionalFact] - public void Required_and_not_required_reference_navigations_with_nrt() - => Test( + public Task Required_and_not_required_reference_navigations_with_nrt() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -869,8 +869,8 @@ public partial class Entity }); [ConditionalFact] - public void Required_and_not_required_collection_navigations_with_nrt() - => Test( + public Task Required_and_not_required_collection_navigations_with_nrt() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -954,8 +954,8 @@ public partial class Entity }); [ConditionalFact] - public void RequiredAttribute_is_not_generated_for_key_property() - => Test( + public Task RequiredAttribute_is_not_generated_for_key_property() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -988,8 +988,8 @@ public partial class Entity Assert.False(model.FindEntityType("TestNamespace.Entity").GetProperty("RequiredString").IsNullable)); [ConditionalFact] - public void ColumnAttribute_is_generated_for_property() - => Test( + public Task ColumnAttribute_is_generated_for_property() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -1088,8 +1088,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) }); [ConditionalFact] - public void MaxLengthAttribute_is_generated_for_property() - => Test( + public Task MaxLengthAttribute_is_generated_for_property() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -1133,8 +1133,8 @@ public partial class Entity }); [ConditionalFact] - public void UnicodeAttribute_is_generated_for_property() - => Test( + public Task UnicodeAttribute_is_generated_for_property() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -1185,8 +1185,8 @@ public partial class Entity }); [ConditionalFact] - public void PrecisionAttribute_is_generated_for_property() - => Test( + public Task PrecisionAttribute_is_generated_for_property() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -1241,8 +1241,8 @@ public partial class Entity }); [ConditionalFact] - public void Comments_are_generated() - => Test( + public Task Comments_are_generated() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -1281,8 +1281,8 @@ public partial class Entity model => { }); [ConditionalFact] - public void Comments_complex_are_generated() - => Test( + public Task Comments_complex_are_generated() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -1331,8 +1331,8 @@ public partial class Entity model => { }); [ConditionalFact] - public void Properties_are_sorted_in_order_of_definition_in_table() - => Test( + public Task Properties_are_sorted_in_order_of_definition_in_table() + => TestAsync( modelBuilder => modelBuilder .Entity( "Entity", @@ -1370,8 +1370,8 @@ public partial class Entity model => { }); [ConditionalFact] - public void Navigation_properties_are_sorted_after_properties_and_collection_are_initialized_in_ctor() - => Test( + public Task Navigation_properties_are_sorted_after_properties_and_collection_are_initialized_in_ctor() + => TestAsync( modelBuilder => modelBuilder .Entity( "Person", @@ -1450,8 +1450,8 @@ public partial class Person }); [ConditionalFact] - public void ForeignKeyAttribute_is_generated_for_composite_fk() - => Test( + public Task ForeignKeyAttribute_is_generated_for_composite_fk() + => TestAsync( modelBuilder => modelBuilder .Entity( "Blog", @@ -1549,8 +1549,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) }); [ConditionalFact] - public void ForeignKeyAttribute_InversePropertyAttribute_is_not_generated_for_alternate_key() - => Test( + public Task ForeignKeyAttribute_InversePropertyAttribute_is_not_generated_for_alternate_key() + => TestAsync( modelBuilder => modelBuilder .Entity( "Blog", @@ -1656,8 +1656,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) }); [ConditionalFact] - public void InverseProperty_when_navigation_property_with_same_type_and_navigation_name() - => Test( + public Task InverseProperty_when_navigation_property_with_same_type_and_navigation_name() + => TestAsync( modelBuilder => modelBuilder .Entity( "Blog", @@ -1709,8 +1709,8 @@ public partial class Post }); [ConditionalFact] - public void InverseProperty_when_navigation_property_with_same_type_and_property_name() - => Test( + public Task InverseProperty_when_navigation_property_with_same_type_and_property_name() + => TestAsync( modelBuilder => modelBuilder .Entity( "Blog", @@ -1762,8 +1762,8 @@ public partial class Post }); [ConditionalFact] - public void InverseProperty_when_navigation_property_with_same_type_and_other_navigation_name() - => Test( + public Task InverseProperty_when_navigation_property_with_same_type_and_other_navigation_name() + => TestAsync( modelBuilder => modelBuilder .Entity( "Blog", @@ -1832,8 +1832,8 @@ public partial class Post }); [ConditionalFact] - public void Entity_with_custom_annotation() - => Test( + public Task Entity_with_custom_annotation() + => TestAsync( modelBuilder => modelBuilder .Entity( "EntityWithAnnotation", @@ -1909,8 +1909,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) skipBuild: true); [ConditionalFact] - public void Entity_property_with_custom_annotation() - => Test( + public Task Entity_property_with_custom_annotation() + => TestAsync( modelBuilder => modelBuilder .Entity( "EntityWithPropertyAnnotation", @@ -1986,8 +1986,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) skipBuild: true); [ConditionalFact] - public void Scaffold_skip_navigations_default() - => Test( + public Task Scaffold_skip_navigations_default() + => TestAsync( modelBuilder => modelBuilder .Entity( "Blog", @@ -2117,8 +2117,8 @@ public partial class Post }); [ConditionalFact] - public void Scaffold_skip_navigations_different_key_type() - => Test( + public Task Scaffold_skip_navigations_different_key_type() + => TestAsync( modelBuilder => modelBuilder .Entity( "Blog", @@ -2243,8 +2243,8 @@ public partial class Post }); [ConditionalFact] - public void Scaffold_skip_navigations_default_data_annotations() - => Test( + public Task Scaffold_skip_navigations_default_data_annotations() + => TestAsync( modelBuilder => modelBuilder .Entity( "Blog", diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/ModelCodeGeneratorTestBase.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/ModelCodeGeneratorTestBase.cs index cb575160ec4..3429f2c81f4 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/ModelCodeGeneratorTestBase.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/ModelCodeGeneratorTestBase.cs @@ -18,7 +18,7 @@ protected ModelCodeGeneratorTestBase(ModelCodeGeneratorTestFixture fixture, ITes _output = output; } - protected void Test( + protected async Task TestAsync( Action buildModel, ModelCodeGenerationOptions options, Action assertScaffold, @@ -68,7 +68,7 @@ protected void Test( if (!skipBuild) { - var assembly = build.BuildInMemory(); + var assembly = await build.BuildInMemoryWithWithAnalyzersAsync(); if (assertModel != null) { diff --git a/test/EFCore.Relational.Specification.Tests/TestUtilities/BuildSource.cs b/test/EFCore.Relational.Specification.Tests/TestUtilities/BuildSource.cs index a3aa2d5068f..804caa51ebc 100644 --- a/test/EFCore.Relational.Specification.Tests/TestUtilities/BuildSource.cs +++ b/test/EFCore.Relational.Specification.Tests/TestUtilities/BuildSource.cs @@ -1,8 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Immutable; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Diagnostics; namespace Microsoft.EntityFrameworkCore.TestUtilities; @@ -128,12 +130,60 @@ public Assembly BuildInMemory() return assembly; } + public async Task BuildInMemoryWithWithAnalyzersAsync() + { + var compilation = CSharpCompilation + .Create( + assemblyName: Path.GetRandomFileName(), + Sources.Select( + s => SyntaxFactory.ParseSyntaxTree( + text: s.Value, + path: s.Key, + options: new CSharpParseOptions( + LanguageVersion.Latest, + EmitDocumentationDiagnostics ? DocumentationMode.Diagnose : DocumentationMode.Parse))), + References.SelectMany(r => r.References), + CreateOptions()) + .WithAnalyzers(ImmutableArray.Create(new UninitializedDbSetDiagnosticSuppressor())); + + var diagnostics = await compilation.GetAllDiagnosticsAsync(); + if (!diagnostics.IsEmpty) + { + throw new InvalidOperationException( + $@"Build failed. + +First diagnostic: +{diagnostics[0]} + +Location: +{diagnostics[0].Location.SourceTree?.GetRoot().FindNode(diagnostics[0].Location.SourceSpan)} + +All diagnostics: +{string.Join(Environment.NewLine, diagnostics)}"); + } + + Assembly assembly; + using (var stream = new MemoryStream()) + { + var result = compilation.Compilation.Emit(stream); + if (!result.Success) + { + throw new InvalidOperationException( + $@"Failed to emit compilation: +{string.Join(Environment.NewLine, result.Diagnostics)}"); + } + + assembly = Assembly.Load(stream.ToArray()); + } + + return assembly; + } + private CSharpCompilationOptions CreateOptions() => new( OutputKind.DynamicallyLinkedLibrary, nullableContextOptions: NullableReferenceTypes ? NullableContextOptions.Enable : NullableContextOptions.Disable, reportSuppressedDiagnostics: false, - generalDiagnosticOption: ReportDiagnostic.Error, specificDiagnosticOptions: new Dictionary { // Displays the text of a warning defined with the #warning directive