Skip to content

Commit 8b93b57

Browse files
committed
Test coverage and setting validation for uses of DisableObjectTracking and MaintainIdentityIntegrity
1 parent 6d59add commit 8b93b57

File tree

7 files changed

+294
-20
lines changed

7 files changed

+294
-20
lines changed

AgileMapper.UnitTests/AgileMapper.UnitTests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@
8383
<Compile Include="..\VersionInfo.cs">
8484
<Link>VersionInfo.cs</Link>
8585
</Compile>
86+
<Compile Include="Configuration\WhenConfiguringObjectTracking.cs" />
87+
<Compile Include="Configuration\WhenConfiguringObjectTrackingIncorrectly.cs" />
8688
<Compile Include="MapperCloning\WhenCloningMapperMemberIgnores.cs" />
8789
<Compile Include="Configuration\WhenConfiguringDerivedTypesIncorrectly.cs" />
8890
<Compile Include="Configuration\WhenConfiguringStringFormatting.cs" />
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
namespace AgileObjects.AgileMapper.UnitTests.Configuration
2+
{
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using Shouldly;
6+
using TestClasses;
7+
using Xunit;
8+
9+
public class WhenConfiguringObjectTracking
10+
{
11+
[Fact]
12+
public void ShouldSupportSpecificDisabledObjectTrackingWithGlobalIdentityIntegrity()
13+
{
14+
using (var mapper = Mapper.CreateNew())
15+
{
16+
mapper
17+
.WhenMapping
18+
.MaintainIdentityIntegrity()
19+
.AndWhenMapping
20+
.From<Product>()
21+
.To<ProductDto>()
22+
.DisableObjectTracking();
23+
24+
var product = new Product();
25+
var sourceProducts = new[] { product, product };
26+
var resultProducts = mapper.Map(sourceProducts).ToANew<IEnumerable<ProductDto>>();
27+
28+
resultProducts.Count().ShouldBe(2);
29+
resultProducts.First().ShouldNotBeSameAs(resultProducts.Second());
30+
31+
var anon = new { Name = "Who?!" };
32+
var sourceAnons = new[] { anon, anon };
33+
var resultAnons = mapper.Map(sourceAnons).ToANew<IEnumerable<PersonViewModel>>();
34+
35+
resultAnons.Count().ShouldBe(2);
36+
resultAnons.First().Name.ShouldBe("Who?!");
37+
resultAnons.First().ShouldBeSameAs(resultAnons.Second());
38+
}
39+
}
40+
41+
[Fact]
42+
public void ShouldSupportSpecificIdentityIntegrityWithGlobalDisabledObjectTracking()
43+
{
44+
using (var mapper = Mapper.CreateNew())
45+
{
46+
mapper
47+
.WhenMapping
48+
.DisableObjectTracking()
49+
.AndWhenMapping
50+
.From<Product>()
51+
.To<ProductDto>()
52+
.MaintainIdentityIntegrity();
53+
54+
var product = new Product();
55+
var sourceProducts = new[] { product, product };
56+
var resultProducts = mapper.Map(sourceProducts).ToANew<IEnumerable<ProductDto>>();
57+
58+
resultProducts.Count().ShouldBe(2);
59+
resultProducts.First().ShouldBeSameAs(resultProducts.Second());
60+
61+
var anon = new { Name = "Who?!" };
62+
var sourceAnons = new[] { anon, anon };
63+
var resultAnons = mapper.Map(sourceAnons).ToANew<IEnumerable<PersonViewModel>>();
64+
65+
resultAnons.Count().ShouldBe(2);
66+
resultAnons.First().Name.ShouldBe("Who?!");
67+
resultAnons.First().ShouldNotBeSameAs(resultAnons.Second());
68+
}
69+
}
70+
}
71+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
namespace AgileObjects.AgileMapper.UnitTests.Configuration
2+
{
3+
using AgileMapper.Configuration;
4+
using Shouldly;
5+
using TestClasses;
6+
using Xunit;
7+
8+
public class WhenConfiguringObjectTrackingIncorrectly
9+
{
10+
[Fact]
11+
public void ShouldErrorIfGlobalIdentityIntegrityConfiguredWithDisabledObjectTracking()
12+
{
13+
using (var mapper = Mapper.CreateNew())
14+
{
15+
mapper.WhenMapping.DisableObjectTracking();
16+
17+
var configEx = Should.Throw<MappingConfigurationException>(() =>
18+
{
19+
mapper.WhenMapping.MaintainIdentityIntegrity();
20+
});
21+
22+
configEx.Message.ShouldContain("Identity integrity cannot be configured");
23+
configEx.Message.ShouldContain("global object tracking disabled");
24+
}
25+
}
26+
27+
[Fact]
28+
public void ShouldErrorIfGlobalIdentityIntegrityConfiguredTwice()
29+
{
30+
using (var mapper = Mapper.CreateNew())
31+
{
32+
mapper.WhenMapping.MaintainIdentityIntegrity();
33+
34+
var configEx = Should.Throw<MappingConfigurationException>(() =>
35+
{
36+
mapper.WhenMapping.MaintainIdentityIntegrity();
37+
});
38+
39+
configEx.Message.ShouldContain("Identity integrity is already configured");
40+
}
41+
}
42+
43+
[Fact]
44+
public void ShouldErrorIfIdentityIntegrityConfiguredTwice()
45+
{
46+
using (var mapper = Mapper.CreateNew())
47+
{
48+
mapper.WhenMapping
49+
.From<Product>()
50+
.To<ProductDto>()
51+
.MaintainIdentityIntegrity();
52+
53+
var configEx = Should.Throw<MappingConfigurationException>(() =>
54+
{
55+
mapper.WhenMapping
56+
.From<Product>()
57+
.To<ProductDto>()
58+
.MaintainIdentityIntegrity();
59+
});
60+
61+
configEx.Message.ShouldContain("Identity integrity is already configured");
62+
configEx.Message.ShouldContain("Product -> ProductDto");
63+
}
64+
}
65+
66+
[Fact]
67+
public void ShouldErrorIfRedundantIdentityIntegrityConfigured()
68+
{
69+
using (var mapper = Mapper.CreateNew())
70+
{
71+
mapper.WhenMapping
72+
.From<Product>()
73+
.To<ProductDto>()
74+
.MaintainIdentityIntegrity();
75+
76+
var configEx = Should.Throw<MappingConfigurationException>(() =>
77+
{
78+
mapper.WhenMapping
79+
.From<MegaProduct>()
80+
.To<ProductDtoMega>()
81+
.MaintainIdentityIntegrity();
82+
});
83+
84+
configEx.Message.ShouldContain("Identity integrity is already configured");
85+
configEx.Message.ShouldContain("Product -> ProductDto");
86+
}
87+
}
88+
89+
[Fact]
90+
public void ShouldErrorIfGlobalObjectTrackingDisabledWithIdentityIntegrityConfigured()
91+
{
92+
using (var mapper = Mapper.CreateNew())
93+
{
94+
mapper.WhenMapping.MaintainIdentityIntegrity();
95+
96+
var configEx = Should.Throw<MappingConfigurationException>(() =>
97+
{
98+
mapper.WhenMapping.DisableObjectTracking();
99+
});
100+
101+
configEx.Message.ShouldContain("Object tracking cannot be disabled");
102+
configEx.Message.ShouldContain("global identity integrity configured");
103+
}
104+
}
105+
106+
[Fact]
107+
public void ShouldErrorIfGlobalObjectTrackingDisabledTwice()
108+
{
109+
using (var mapper = Mapper.CreateNew())
110+
{
111+
mapper.WhenMapping.DisableObjectTracking();
112+
113+
var configEx = Should.Throw<MappingConfigurationException>(() =>
114+
{
115+
mapper.WhenMapping.DisableObjectTracking();
116+
});
117+
118+
configEx.Message.ShouldContain("Object tracking is already disabled");
119+
}
120+
}
121+
122+
[Fact]
123+
public void ShouldErrorIfObjectTrackingDisabledTwice()
124+
{
125+
using (var mapper = Mapper.CreateNew())
126+
{
127+
mapper.WhenMapping
128+
.From<PersonViewModel>()
129+
.To<Person>()
130+
.DisableObjectTracking();
131+
132+
var configEx = Should.Throw<MappingConfigurationException>(() =>
133+
{
134+
mapper.WhenMapping
135+
.From<PersonViewModel>()
136+
.To<Person>()
137+
.DisableObjectTracking();
138+
});
139+
140+
configEx.Message.ShouldContain("Object tracking is already disabled");
141+
configEx.Message.ShouldContain("PersonViewModel -> Person");
142+
}
143+
}
144+
}
145+
}

AgileMapper/Api/Configuration/MappingConfigStartingPoint.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ private IGlobalConfigSettings UseNamePatterns(IEnumerable<string> patterns)
211211
/// </returns>
212212
public IGlobalConfigSettings MaintainIdentityIntegrity()
213213
{
214-
_mapperContext.UserConfigurations.Add(MappedObjectCachingSettings.CacheAll(_mapperContext));
214+
_mapperContext.UserConfigurations.Add(MappedObjectCachingSettings.CacheAll);
215215
return this;
216216
}
217217

@@ -227,7 +227,7 @@ public IGlobalConfigSettings MaintainIdentityIntegrity()
227227
/// </returns>
228228
public IGlobalConfigSettings DisableObjectTracking()
229229
{
230-
_mapperContext.UserConfigurations.Add(MappedObjectCachingSettings.CacheNone(_mapperContext));
230+
_mapperContext.UserConfigurations.Add(MappedObjectCachingSettings.CacheNone);
231231
return this;
232232
}
233233

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,78 @@
11
namespace AgileObjects.AgileMapper.Configuration
22
{
3+
using ReadableExpressions.Extensions;
4+
35
internal class MappedObjectCachingSettings : UserConfiguredItemBase
46
{
7+
#region Singleton Instances
8+
9+
public static readonly MappedObjectCachingSettings CacheAll =
10+
new MappedObjectCachingSettings(ForAllMappings(MapperContext.Default), cache: true);
11+
12+
public static readonly MappedObjectCachingSettings CacheNone =
13+
new MappedObjectCachingSettings(ForAllMappings(MapperContext.Default), cache: false);
14+
15+
private static MappingConfigInfo ForAllMappings(MapperContext mapperContext)
16+
=> MappingConfigInfo.AllRuleSetsSourceTypesAndTargetTypes(mapperContext);
17+
18+
#endregion
19+
520
public MappedObjectCachingSettings(MappingConfigInfo configInfo, bool cache)
621
: base(configInfo)
722
{
823
Cache = cache;
924
}
1025

11-
#region Factory Methods
26+
public bool Cache { get; }
1227

13-
public static MappedObjectCachingSettings CacheAll(MapperContext mapperContext)
14-
=> new MappedObjectCachingSettings(ForAllMappings(mapperContext), cache: true);
28+
public override bool ConflictsWith(UserConfiguredItemBase otherItem)
29+
{
30+
if ((otherItem == this) ||
31+
((this == CacheNone) && (otherItem == CacheAll)) ||
32+
((this == CacheAll) && (otherItem == CacheNone)))
33+
{
34+
return true;
35+
}
1536

16-
public static MappedObjectCachingSettings CacheNone(MapperContext mapperContext)
17-
=> new MappedObjectCachingSettings(ForAllMappings(mapperContext), cache: false);
37+
if (base.ConflictsWith(otherItem))
38+
{
39+
var otherSettings = (MappedObjectCachingSettings)otherItem;
1840

19-
private static MappingConfigInfo ForAllMappings(MapperContext mapperContext)
20-
=> MappingConfigInfo.AllRuleSetsSourceTypesAndTargetTypes(mapperContext);
41+
return (otherSettings.Cache == Cache);
42+
}
2143

22-
#endregion
44+
return false;
45+
}
2346

24-
public bool Cache { get; }
47+
public string GetConflictMessage(MappedObjectCachingSettings conflicting)
48+
{
49+
if (conflicting == this)
50+
{
51+
return GetRedundantSettingsConflictMessage();
52+
}
53+
54+
if ((this == CacheAll) && (conflicting == CacheNone))
55+
{
56+
return "Object tracking cannot be disabled globally with global identity integrity configured";
57+
}
58+
59+
if ((this == CacheNone) && (conflicting == CacheAll))
60+
{
61+
return "Identity integrity cannot be configured globally with global object tracking disabled";
62+
}
63+
64+
var sourceType = ConfigInfo.SourceType.GetFriendlyName();
65+
var targetType = ConfigInfo.TargetType.GetFriendlyName();
66+
var typeSettings = $" when mapping {sourceType} -> {targetType}";
67+
68+
return GetRedundantSettingsConflictMessage(typeSettings);
69+
}
70+
71+
private string GetRedundantSettingsConflictMessage(string typeSettings = null)
72+
{
73+
return Cache
74+
? "Identity integrity is already configured" + typeSettings
75+
: "Object tracking is already disabled" + typeSettings;
76+
}
2577
}
2678
}

AgileMapper/Configuration/UserConfigurationSet.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,17 @@ public UserConfigurationSet(MapperContext mapperContext)
3939
DerivedTypes = new DerivedTypePairSet();
4040
}
4141

42-
#region Tracking Modes
42+
#region Mapped Object Caching Settings
4343

4444
public void Add(MappedObjectCachingSettings settings)
4545
{
46+
ThrowIfConflictingItemExists(
47+
settings,
48+
_mappedObjectCachingSettings,
49+
(s, conflicting) => conflicting.GetConflictMessage(s));
50+
4651
_mappedObjectCachingSettings.Add(settings);
52+
_mappedObjectCachingSettings.Sort();
4753
}
4854

4955
public MappedObjectCachingMode CacheMappedObjects(IBasicMapperData basicData)

0 commit comments

Comments
 (0)