|
| 1 | +using System; |
| 2 | +using System.Linq; |
| 3 | +using System.Reflection; |
| 4 | +using Microsoft.EntityFrameworkCore; |
| 5 | +using Microsoft.EntityFrameworkCore.Metadata; |
| 6 | +using Microsoft.Extensions.Caching.Memory; |
| 7 | +using Thinktecture.EntityFrameworkCore.Storage.ValueConversion; |
| 8 | +using Thinktecture.Runtime.Tests.TestEntities; |
| 9 | +using Thinktecture.Runtime.Tests.TestEnums; |
| 10 | + |
| 11 | +// ReSharper disable InconsistentNaming |
| 12 | +namespace Thinktecture.Runtime.Tests.Extensions.ModelBuilderExtensionsTests |
| 13 | +{ |
| 14 | + public class HasValueObjectConversion : IDisposable |
| 15 | + { |
| 16 | + private static readonly Type _validateableConverterType = typeof(ValueObjectValueConverterFactory).GetNestedTypes(BindingFlags.NonPublic) |
| 17 | + .Single(t => t.Name.StartsWith("ValidatableEnumValueConverter", StringComparison.Ordinal)); |
| 18 | + |
| 19 | + private static readonly Type _testEnumConverterType = _validateableConverterType.MakeGenericType(typeof(TestEnum), typeof(string)); |
| 20 | + |
| 21 | + private static readonly Type _converterType = typeof(ValueObjectValueConverterFactory).GetNestedTypes(BindingFlags.NonPublic) |
| 22 | + .Single(t => t.Name.StartsWith("ValueObjectValueConverter", StringComparison.Ordinal)); |
| 23 | + |
| 24 | + private readonly TestDbContext _ctx = new(new DbContextOptionsBuilder<TestDbContext>() |
| 25 | + .UseSqlite("DataSource=:memory:") |
| 26 | + .EnableServiceProviderCaching(false) |
| 27 | + .Options, |
| 28 | + ValueConverterRegistration.PropertyConfiguration); |
| 29 | + |
| 30 | + [Fact] |
| 31 | + public void Should_add_converters_for_structs_and_classes() |
| 32 | + { |
| 33 | + var entityType = _ctx.Model.FindEntityType(typeof(TestEntity_with_Enum_and_ValueObjects)); |
| 34 | + |
| 35 | + ValidateConverter(entityType, nameof(TestEntity_with_Enum_and_ValueObjects.TestEnum), _testEnumConverterType); |
| 36 | + |
| 37 | + ValidateConverter(entityType, nameof(TestEntity_with_Enum_and_ValueObjects.TestSmartEnum_Class_IntBased), _converterType.MakeGenericType(typeof(TestSmartEnum_Class_IntBased), typeof(int))); |
| 38 | + ValidateConverter(entityType, nameof(TestEntity_with_Enum_and_ValueObjects.TestSmartEnum_Class_StringBased), _converterType.MakeGenericType(typeof(TestSmartEnum_Class_StringBased), typeof(string))); |
| 39 | + ValidateConverter(entityType, nameof(TestEntity_with_Enum_and_ValueObjects.TestSmartEnum_Struct_IntBased), _validateableConverterType.MakeGenericType(typeof(TestSmartEnum_Struct_IntBased), typeof(int))); |
| 40 | + ValidateConverter(entityType, nameof(TestEntity_with_Enum_and_ValueObjects.TestSmartEnum_Struct_StringBased), _validateableConverterType.MakeGenericType(typeof(TestSmartEnum_Struct_StringBased), typeof(string))); |
| 41 | + ValidateConverter(entityType, nameof(TestEntity_with_Enum_and_ValueObjects.NullableTestSmartEnum_Struct_StringBased), _validateableConverterType.MakeGenericType(typeof(TestSmartEnum_Struct_StringBased), typeof(string))); |
| 42 | + } |
| 43 | + |
| 44 | +#if COMPLEX_TYPES |
| 45 | + [Fact] |
| 46 | + public void Should_add_converters_for_complex_types() |
| 47 | + { |
| 48 | + var entityType = _ctx.Model.FindEntityType(typeof(TestEntityWithComplexType)) ?? throw new Exception("Entity not found"); |
| 49 | + var complexProperty = entityType.FindComplexProperty(nameof(TestEntityWithComplexType.TestComplexType)) ?? throw new Exception("Complex type property not found"); |
| 50 | + |
| 51 | + ValidateConverter(complexProperty.ComplexType, nameof(TestComplexType.TestEnum)); |
| 52 | + } |
| 53 | + |
| 54 | + [Fact] |
| 55 | + public void Should_add_converters_for_complex_types_inside_complex_value_object() |
| 56 | + { |
| 57 | + var entityType = _ctx.Model.FindEntityType(typeof(ComplexValueObjectWithComplexType)) ?? throw new Exception("Entity not found"); |
| 58 | + var complexProperty = entityType.FindComplexProperty(nameof(ComplexValueObjectWithComplexType.TestComplexType)) ?? throw new Exception("Complex type property not found"); |
| 59 | + |
| 60 | + ValidateConverter(complexProperty.ComplexType, nameof(TestComplexType.TestEnum)); |
| 61 | + } |
| 62 | + |
| 63 | + [Fact] |
| 64 | + public void Should_add_converters_for_complex_value_object_as_complex_type() |
| 65 | + { |
| 66 | + var entityType = _ctx.Model.FindEntityType(typeof(TestEntityWithComplexValueObjectAsComplexType)) ?? throw new Exception("Entity not found"); |
| 67 | + var complexProperty = entityType.FindComplexProperty(nameof(TestEntityWithComplexValueObjectAsComplexType.TestComplexType)) ?? throw new Exception("Complex type property not found"); |
| 68 | + |
| 69 | + ValidateConverter(complexProperty.ComplexType, nameof(TestComplexValueObject.TestEnum)); |
| 70 | + } |
| 71 | +#endif |
| 72 | + |
| 73 | + [Fact] |
| 74 | + public void Should_add_converters_for_owned_types() |
| 75 | + { |
| 76 | + var entityType = _ctx.Model.FindEntityType(typeof(TestEntity_with_OwnedTypes)); |
| 77 | + ValidateConverter(entityType, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 78 | + |
| 79 | + var inline_inline = entityType.FindNavigation(nameof(TestEntity_with_OwnedTypes.Inline_Inline)).TargetEntityType; |
| 80 | + var inline_inline_inner = inline_inline.FindNavigation(nameof(OwnedEntity_Owns_Inline.InlineEntity)).TargetEntityType; |
| 81 | + ValidateConverter(inline_inline, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 82 | + ValidateConverter(inline_inline_inner, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 83 | + |
| 84 | + var inline_separateOne = entityType.FindNavigation(nameof(TestEntity_with_OwnedTypes.Inline_SeparateOne)).TargetEntityType; |
| 85 | + var inline_separateOne_inner = inline_separateOne.FindNavigation(nameof(OwnedEntity_Owns_SeparateOne.SeparateEntity)).TargetEntityType; |
| 86 | + ValidateConverter(inline_separateOne, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 87 | + ValidateConverter(inline_separateOne_inner, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 88 | + |
| 89 | + var inline_SeparateMany = entityType.FindNavigation(nameof(TestEntity_with_OwnedTypes.Inline_SeparateMany)).TargetEntityType; |
| 90 | + var inline_SeparateMany_inner = inline_SeparateMany.FindNavigation(nameof(OwnedEntity_Owns_SeparateMany.SeparateEntities)).TargetEntityType; |
| 91 | + ValidateConverter(inline_SeparateMany, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 92 | + ValidateConverter(inline_SeparateMany_inner, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 93 | + |
| 94 | + var separateMany_Inline = entityType.FindNavigation(nameof(TestEntity_with_OwnedTypes.SeparateMany_Inline)).TargetEntityType; |
| 95 | + var separateMany_Inline_inner = separateMany_Inline.FindNavigation(nameof(OwnedEntity_Owns_Inline.InlineEntity)).TargetEntityType; |
| 96 | + ValidateConverter(separateMany_Inline, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 97 | + ValidateConverter(separateMany_Inline_inner, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 98 | + |
| 99 | + var separateMany_SeparateOne = entityType.FindNavigation(nameof(TestEntity_with_OwnedTypes.SeparateMany_SeparateOne)).TargetEntityType; |
| 100 | + var separateMany_SeparateOne_inner = separateMany_SeparateOne.FindNavigation(nameof(OwnedEntity_Owns_SeparateOne.SeparateEntity)).TargetEntityType; |
| 101 | + ValidateConverter(separateMany_SeparateOne, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 102 | + ValidateConverter(separateMany_SeparateOne_inner, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 103 | + |
| 104 | + var separateMany_SeparateMany = entityType.FindNavigation(nameof(TestEntity_with_OwnedTypes.SeparateMany_SeparateMany)).TargetEntityType; |
| 105 | + var separateMany_SeparateMany_inner = separateMany_SeparateMany.FindNavigation(nameof(OwnedEntity_Owns_SeparateMany.SeparateEntities)).TargetEntityType; |
| 106 | + ValidateConverter(separateMany_SeparateMany, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 107 | + ValidateConverter(separateMany_SeparateMany_inner, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 108 | + |
| 109 | + var separateOne_Inline = entityType.FindNavigation(nameof(TestEntity_with_OwnedTypes.SeparateOne_Inline)).TargetEntityType; |
| 110 | + var separateOne_Inline_inner = separateOne_Inline.FindNavigation(nameof(OwnedEntity_Owns_Inline.InlineEntity)).TargetEntityType; |
| 111 | + ValidateConverter(separateOne_Inline, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 112 | + ValidateConverter(separateOne_Inline_inner, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 113 | + |
| 114 | + var separateOne_SeparateOne = entityType.FindNavigation(nameof(TestEntity_with_OwnedTypes.SeparateOne_SeparateOne)).TargetEntityType; |
| 115 | + var separateOne_SeparateOne_inner = separateOne_SeparateOne.FindNavigation(nameof(OwnedEntity_Owns_SeparateOne.SeparateEntity)).TargetEntityType; |
| 116 | + ValidateConverter(separateOne_SeparateOne, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 117 | + ValidateConverter(separateOne_SeparateOne_inner, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 118 | + |
| 119 | + var separateOne_SeparateMany = entityType.FindNavigation(nameof(TestEntity_with_OwnedTypes.SeparateOne_SeparateMany)).TargetEntityType; |
| 120 | + var separateOne_SeparateMany_inner = separateOne_SeparateMany.FindNavigation(nameof(OwnedEntity_Owns_SeparateMany.SeparateEntities)).TargetEntityType; |
| 121 | + ValidateConverter(separateOne_SeparateMany, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 122 | + ValidateConverter(separateOne_SeparateMany_inner, nameof(TestEntity_with_OwnedTypes.TestEnum)); |
| 123 | + } |
| 124 | + |
| 125 | + private static void ValidateConverter( |
| 126 | +#if COMPLEX_TYPES |
| 127 | + ITypeBase |
| 128 | +#else |
| 129 | + IEntityType |
| 130 | +#endif |
| 131 | + entityType, string propertyName, Type converterType = null) |
| 132 | + { |
| 133 | + var property = entityType.FindProperty(propertyName) ?? throw new Exception($"Property with the name '{propertyName}' not found."); |
| 134 | + property.GetValueConverter().Should().BeOfType(converterType ?? _testEnumConverterType); |
| 135 | + } |
| 136 | + |
| 137 | + public void Dispose() |
| 138 | + { |
| 139 | + _ctx.Dispose(); |
| 140 | + } |
| 141 | + } |
| 142 | +} |
0 commit comments