Browse Source

Add test covering explicit case of nullable value type setting

pull/18970/head
namtab00 3 years ago
parent
commit
736bb69a81
  1. 9
      framework/src/Volo.Abp.Core/Volo/Abp/ObjectHelper.cs
  2. 87
      framework/test/Volo.Abp.Core.Tests/Volo/Abp/ObjectHelper_Tests.cs

9
framework/src/Volo.Abp.Core/Volo/Abp/ObjectHelper.cs

@ -57,16 +57,21 @@ public static class ObjectHelper
return null; return null;
} }
var propertyInfo = obj?.GetType() var propertyInfo = obj?.GetType()
.GetProperties() .GetProperties()
.FirstOrDefault(x => x.Name == memberExpression.Member.Name && x.GetSetMethod(true) != null); .FirstOrDefault(x => x.Name == memberExpression.Member.Name);
if (propertyInfo == null) if (propertyInfo == null)
{ {
return null; return null;
} }
var propPrivateSetMethod = propertyInfo.GetSetMethod(true);
if (propPrivateSetMethod == null)
{
return null;
}
if (ignoreAttributeTypes != null && ignoreAttributeTypes.Any(ignoreAttribute => propertyInfo.IsDefined(ignoreAttribute, true))) if (ignoreAttributeTypes != null && ignoreAttributeTypes.Any(ignoreAttribute => propertyInfo.IsDefined(ignoreAttribute, true)))
{ {
return null; return null;

87
framework/test/Volo.Abp.Core.Tests/Volo/Abp/ObjectHelper_Tests.cs

@ -40,27 +40,88 @@ public class ObjectHelper_Tests
} }
[Fact] [Fact]
public void TrySetPropertyWithValueType_SetsCorrectly() public void TrySetProperty_WithNullableNewValueType_SetsCorrectly()
{ {
// Arrange // Arrange
var testClass = new MyClass(); var sut = new AbstractParentImpl();
const long newValue = 10; long? newValue = 10;
// Act & Assert // Act & Assert
ObjectHelper.TrySetProperty(testClass, x => x.Number, () => newValue); var sutAsIFirst = (IFirst)sut;
testClass.Number.ShouldBe(newValue);
ObjectHelper.TrySetProperty(sutAsIFirst, x => x.ValueProp1FromIFirst, () => newValue);
sutAsIFirst.ValueProp1FromIFirst.ShouldBe(newValue.Value);
ObjectHelper.TrySetProperty(sutAsIFirst, x => x.ValueProp2FromIFirst, () => newValue);
sutAsIFirst.ValueProp2FromIFirst.ShouldBe(newValue.Value);
ObjectHelper.TrySetProperty(sutAsIFirst, x => x.ValueProp3FromIFirst, () => newValue);
sutAsIFirst.ValueProp3FromIFirst.ShouldNotBe(newValue.Value); // private set on implementation not accessible
ObjectHelper.TrySetProperty(sutAsIFirst, x => x.ValueProp4FromIFirst, () => newValue);
sutAsIFirst.ValueProp4FromIFirst.ShouldNotBe(newValue.Value); // readonly
ObjectHelper.TrySetProperty(sutAsIFirst, x => x.ValueProp5FromIFirst, () => newValue,
ignoreAttributeTypes: typeof(IgnoreDataMemberAttribute));
sutAsIFirst.ValueProp5FromIFirst.ShouldNotBe(newValue.Value); // ignore by attribute
var sutAsISecond = (ISecond)sut;
ObjectHelper.TrySetProperty(sutAsISecond, x => x.ValueProp1FromISecond, () => newValue);
sutAsISecond.ValueProp1FromISecond.ShouldNotBe(newValue.Value); // readonly
}
internal interface IFirst
{
public long ValueProp1FromIFirst { get; }
public long ValueProp2FromIFirst { get; }
public long ValueProp3FromIFirst { get; }
public long ValueProp4FromIFirst { get; }
public long ValueProp5FromIFirst { get; }
}
internal interface ISecond
{
public long ValueProp1FromISecond { get; }
}
ObjectHelper.TrySetProperty(testClass, x => x.Number2, () => newValue); internal interface IHasKey<out TKey>
testClass.Number2.ShouldBe(newValue); {
TKey Id { get; }
}
ObjectHelper.TrySetProperty(testClass, x => x.Number3, () => newValue); internal interface IHaveMixedProps : IFirst, ISecond
testClass.Number3.ShouldBe(newValue); {
}
ObjectHelper.TrySetProperty(testClass, x => x.Number4, () => newValue); abstract internal class GenericBase<TKey> : IHasKey<TKey>
testClass.Number4.ShouldBe(0); // readonly {
public virtual TKey Id { get; protected set; }
}
ObjectHelper.TrySetProperty(testClass, x => x.Number5, () => newValue, ignoreAttributeTypes: typeof(IgnoreDataMemberAttribute)); abstract internal class AbstractParent<TKey> : GenericBase<TKey>, IHaveMixedProps
testClass.Number5.ShouldNotBe(newValue); // ignore by attribute {
public long ValueProp1FromIFirst { get; set; }
public long ValueProp2FromIFirst { get; protected set; }
public long ValueProp3FromIFirst { get; private set; }
public long ValueProp4FromIFirst { get; }
[IgnoreDataMember] public long ValueProp5FromIFirst { get; }
public long ValueProp1FromISecond { get; }
}
internal class AbstractParentImpl : AbstractParent<long>
{
public long OwnProp1 { get; set; }
public string OwnProp2 { get; set; }
} }
class MyClass class MyClass

Loading…
Cancel
Save