AutoMapProperty/AutoMapProperty.Tests/MappingRegressionTests.cs
2026-10-25 23:48:22 +01:00

199 lines
8.3 KiB
C#

using Microsoft.CodeAnalysis;
using Xunit;
namespace AutoMapProperty.Tests;
public class MappingRegressionTests
{
[Fact]
public void NullableNestedDtosMapNullAndNonNullValues()
{
var compilation = new GeneratorTestCompilation("""
namespace Fixtures
{
public class Child
{
[AutoMapProperty("Response")]
public int Value { get; set; }
}
public class Parent
{
[AutoMapProperty("Response", typeof(ChildResponse), Nullability = AutoMapNullability.Nullable)]
public Child Child { get; set; } = new Child();
}
public static class Check
{
public static bool Run()
{
var parent = new Parent { Child = new Child { Value = 42 } };
var dto = new ParentResponse().ApplyFrom(null, parent);
if (dto.Child.Value != 42 || dto.GetProjectorFrom(null).Compile()(parent).Child.Value != 42)
return false;
dto.Child = null;
dto.ApplyTo(null, parent);
if (parent.Child != null || new ParentResponse().ApplyFrom(null, parent).Child != null ||
dto.GetProjectorFrom(null).Compile()(parent).Child != null)
return false;
if (!ParentResponse.EqualExpression(null, parent).Compile()(dto) ||
!dto.Equals(new ParentResponse { Child = null }))
return false;
dto.Child = new ChildResponse { Value = 17 };
dto.ApplyTo(null, parent);
return parent.Child.Value == 17;
}
}
}
""");
Assert.Equal(NullableAnnotation.Annotated, compilation.Property("Fixtures.ParentResponse", "Child").Type.NullableAnnotation);
Assert.Equal(true, compilation.Evaluate());
}
[Fact]
public void InheritedGeneratedPropertiesParticipateInMappings()
{
var compilation = new GeneratorTestCompilation("""
namespace Fixtures
{
public class Base
{
[AutoMapProperty("Request", Nullability = AutoMapNullability.NonNullable)]
public string? Name { get; set; }
}
public class Derived : Base
{
[AutoMapProperty("Request")]
public int Value { get; set; }
}
public partial class DerivedRequest : BaseRequest { }
public static class Check
{
public static bool Run()
{
var entity = new Derived { Name = "name", Value = 42 };
var dto = new DerivedRequest().ApplyFrom(null, entity);
var projected = dto.GetProjectorFrom(null).Compile()(entity);
dto.Name = "changed";
dto.ApplyTo(null, entity);
return entity.Name == "changed" && projected.Name == "name" && projected.Value == 42;
}
}
}
""");
Assert.Equal(true, compilation.Evaluate());
}
[Fact]
public void CustomConvertersReceiveOverriddenNullableValues()
{
var compilation = new GeneratorTestCompilation("""
namespace Fixtures
{
public class Entity
{
[AutoMapProperty("Request", typeof(string), nameof(Parse), nameof(Format), Nullability = AutoMapNullability.Nullable)]
public int Value { get; set; }
public static int Parse(IServiceProvider providers, Entity entity, string? value) => value == null ? 0 : int.Parse(value);
public static string Format(IServiceProvider providers, Entity entity, int value) => value.ToString();
}
public static class Check
{
public static bool Run()
{
var entity = new Entity { Value = 42 };
var dto = new EntityRequest().ApplyFrom(null, entity);
if (dto.Value != "42" || dto.GetProjectorFrom(null).Compile()(entity).Value != "42")
return false;
dto.Value = null;
dto.ApplyTo(null, entity);
return entity.Value == 0;
}
}
}
""");
Assert.Equal(true, compilation.Evaluate());
}
[Fact]
public void FiltersMappingAttributesFromSharedListsAndKeepsValidationAttributes()
{
var compilation = new GeneratorTestCompilation("""
namespace Fixtures
{
public class Entity
{
[System.ComponentModel.DataAnnotations.Required, AutoMapProperty("Response", Nullability = AutoMapNullability.Nullable)]
public string Value { get; set; } = "initial";
}
}
""");
compilation.AssertCompiles();
var attribute = Assert.Single(compilation.Property("Fixtures.EntityResponse", "Value").GetAttributes());
Assert.Equal("RequiredAttribute", attribute.AttributeClass!.Name);
}
[Fact]
public void NestedCollectionsAndArrayTypeReplacementsKeepMappingAndInitializerBehavior()
{
var compilation = new GeneratorTestCompilation("""
namespace Fixtures
{
public class Child
{
[AutoMapProperty("Response")]
public int Value { get; set; }
}
public class Parent
{
[AutoMapProperty("Response", typeof(ChildResponse[]), Nullability = AutoMapNullability.Nullable)]
public Child[] Children { get; set; } = Array.Empty<Child>();
}
public static class Check
{
public static bool Run()
{
var parent = new Parent { Children = new[] { new Child { Value = 42 } } };
var dto = new ParentResponse().ApplyFrom(null, parent);
if (dto.Children[0].Value != 42 || dto.GetProjectorFrom(null).Compile()(parent).Children[0].Value != 42)
return false;
dto.Children[0].Value = 17;
dto.ApplyTo(null, parent);
if (parent.Children[0].Value != 17)
return false;
dto.Children = null;
dto.ApplyTo(null, parent);
return parent.Children.Length == 0;
}
}
}
""");
Assert.Equal(true, compilation.Evaluate());
}
[Fact]
public void SupportsInterfacesComputedPropertiesAndNullTypeArguments()
{
var compilation = new GeneratorTestCompilation("""
namespace Fixtures
{
public interface ISource
{
[AutoMapProperty("Request", Nullability = AutoMapNullability.Nullable)]
string Name { get; }
}
public class Entity
{
[AutoMapProperty("Response", null, Nullability = AutoMapNullability.NonNullable)]
public string? Name => "name";
}
public static class Check
{
public static bool Run() => new EntityResponse().ApplyFrom(null, new Entity()).Name == "name";
}
}
""");
Assert.Equal(NullableAnnotation.Annotated, compilation.Property("Fixtures.ISourceRequest", "Name").Type.NullableAnnotation);
Assert.Equal(NullableAnnotation.NotAnnotated, compilation.Property("Fixtures.EntityResponse", "Name").Type.NullableAnnotation);
Assert.Equal(true, compilation.Evaluate());
}
}