8000 Add PersistentServicesRegistry tests · dotnet/aspnetcore@995d550 · GitHub
[go: up one dir, main page]

Skip to content

Commit 995d550

Browse files
committed
Add PersistentServicesRegistry tests
1 parent baf5473 commit 995d550

File tree

5 files changed

+655
-65
lines changed

5 files changed

+655
-65
lines changed

src/Components/Components/src/PersistentState/ComponentStatePersistenceManager.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,14 @@ public ComponentStatePersistenceManager(ILogger<ComponentStatePersistenceManager
3636
public ComponentStatePersistenceManager(ILogger<ComponentStatePersistenceManager> logger, IServiceProvider serviceProvider) : this(logger)
3737
{
3838
_servicesRegistry = new PersistentServicesRegistry(serviceProvider);
39-
_servicesRegistry.RegisterForPersistence(State);
4039
}
4140

41+
// For testing purposes only
42+
internal PersistentServicesRegistry? ServicesRegistry => _servicesRegistry;
43+
44+
// For testing purposes only
45+
internal List<PersistComponentStateRegistration> RegisteredCallbacks => _registeredCallbacks;
46+
4247
/// <summary>
4348
/// Gets the <see cref="ComponentStatePersistenceManager"/> associated with the <see cref="ComponentStatePersistenceManager"/>.
4449
/// </summary>
@@ -73,6 +78,9 @@ public Task PersistStateAsync(IPersistentComponentStateStore store, Renderer ren
7378

7479
async Task PauseAndPersistState()
7580
{
81+
// Ensure that we register the services before we start persisting the state.
82+
_servicesRegistry?.RegisterForPersistence(State);
83+
7684
State.PersistingState = true;
7785

7886
if (store is IEnumerable<IPersistentComponentStateStore> compositeStore)

src/Components/Components/src/PersistentState/PersistentServicesRegistry.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,19 @@ internal sealed class PersistentServicesRegistry
2323
private IPersistentComponentRegistration[] _registrations;
2424
private List<PersistingComponentStateSubscription> _subscriptions = [];
2525
private static readonly ConcurrentDictionary<Type, PropertiesAccessor> _cachedAccessorsByType = new();
26-
public IComponentRenderMode? RenderMode { get; internal set; }
2726

2827
public PersistentServicesRegistry(IServiceProvider serviceProvider)
2928
{
3029
var registrations = serviceProvider.GetRequiredService<IEnumerable<IPersistentComponentRegistration>>();
3130
_serviceProvider = serviceProvider;
3231
_persistentServiceTypeCache = new PersistentServiceTypeCache();
33-
_registrations = [.. registrations.DistinctBy(r => (r.Assembly, r.FullTypeName)).OrderBy(r => r.Assembly).ThenBy(r => r.FullTypeName)];
32+
_registrations = ResolveRegistrations(registrations);
3433
}
3534

35+
internal IComponentRenderMode? RenderMode { get; set; }
36+
37+
internal IReadOnlyList<IPersistentComponentRegistration> Registrations => _registrations;
38+
3639
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
3740
internal void RegisterForPersistence(PersistentComponentState state)
3841
{
@@ -61,7 +64,7 @@ internal void RegisterForPersistence(PersistentComponentState state)
6164
}, renderMode));
6265
}
6366

64-
if(RenderMode != null)
67+
if (RenderMode != null)
6568
{
6669
subscriptions.Add(state.RegisterOnPersisting(() =>
6770
{
@@ -91,11 +94,9 @@ private static void PersistInstanceState(object instance, Type type, PersistentC
9194
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
9295
internal void Restore(PersistentComponentState state)
9396
{
94-
if (_registrations.Length == 0 &&
95-
state.TryTakeFromJson<PersistentComponentRegistration[]>(_registryKey, out var registry) &&
96-
registry != null)
97+
if (state.TryTakeFromJson<PersistentComponentRegistration[]>(_registryKey, out var registry) && registry != null)
9798
{
98-
_registrations = registry ?? [];
99+
_registrations = ResolveRegistrations(_registrations.Concat(registry));
99100
}
100101

101102
RestoreRegistrationsIfAvailable(state);
@@ -134,6 +135,8 @@ private static void RestoreInstanceState(object instance, Type type, PersistentC
134135
}
135136
}
136137

138+
private static IPersistentComponentRegistration[] ResolveRegistrations(IEnumerable<IPersistentComponentRegistration> registrations) => [.. registrations.DistinctBy(r => (r.Assembly, r.FullTypeName)).OrderBy(r => r.Assembly).ThenBy(r => r.FullTypeName)];
139+
137140
private Type? ResolveType(string assembly, string fullTypeName) => _persistentServiceTypeCache.GetPersistentService(assembly, fullTypeName);
138141

139142
private sealed class PropertiesAccessor

src/Components/Components/test/Lifetime/ComponentApplicationStateTest.cs renamed to src/Components/Components/test/PersistentState/ComponentApplicationStateTest.cs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class ComponentApplicationStateTest
1111
public void InitializeExistingState_SetupsState()
1212
{
1313
// Arrange
14-
var applicationState = new PersistentComponentState(new Dictionary<string, byte[]>(), new List<PersistComponentStateRegistration>());
14+
var applicationState = new PersistentComponentState(new Dictionary<string, byte[]>(), []);
1515
var existingState = new Dictionary<string, byte[]>
1616
{
1717
["MyState"] = JsonSerializer.SerializeToUtf8Bytes(new byte[] { 1, 2, 3, 4 })
@@ -29,7 +29,7 @@ public void InitializeExistingState_SetupsState()
2929
public void InitializeExistingState_ThrowsIfAlreadyInitialized()
3030
{
3131
// Arrange
32-
var applicationState = new PersistentComponentState(new Dictionary<string, byte[]>(), new List<PersistComponentStateRegistration>());
32+
var applicationState = new PersistentComponentState(new Dictionary<string, byte[]>(), []);
3333
var existingState = new Dictionary<string, byte[]>
3434
{
3535
["MyState"] = new byte[] { 1, 2, 3, 4 }
@@ -41,11 +41,25 @@ public void InitializeExistingState_ThrowsIfAlreadyInitialized()
4141
Assert.Throws<InvalidOperationException>(() => applicationState.InitializeExistingState(existingState));
4242
}
4343

44+
[Fact]
45+
public void RegisterOnPersisting_ThrowsIfCalledDuringOnPersisting()
46+
{
47+
// Arrange
48+
var currentState = new Dictionary<string, byte[]>();
49+
var applicationState = new PersistentComponentState(currentState, [])
50+
{
51+
PersistingState = true
52+
};
53+
54+
// Act & Assert
55+
Assert.Throws<InvalidOperationException>(() => applicationState.RegisterOnPersisting(() => Task.CompletedTask));
56+
}
57+
4458
[Fact]
4559
public void TryRetrieveState_ReturnsStateWhenItExists()
4660
{
4761
// Arrange
48-
var applicationState = new PersistentComponentState(new Dictionary<string, byte[]>(), new List<PersistComponentStateRegistration>());
62+
var applicationState = new PersistentComponentState(new Dictionary<string, byte[]>(), []);
4963
var existingState = new Dictionary<string, byte[]>
5064
{
5165
["MyState"] = JsonSerializer.SerializeToUtf8Bytes(new byte[] { 1, 2, 3, 4 })
@@ -65,7 +79,7 @@ public void PersistState_SavesDataToTheStoreAsync()
6579
{
6680
// Arrange
6781
var currentState = new Dictionary<string, byte[]>();
68-
var applicationState = new PersistentComponentState(currentState, new List<PersistComponentStateRegistration>())
82+
var applicationState = new PersistentComponentState(currentState, [])
6983
{
7084
PersistingState = true
7185
};
@@ -84,7 +98,7 @@ public void PersistState_ThrowsForDuplicateKeys()
8498
{
8599
// Arrange
86100
var currentState = new Dictionary<string, byte[]>();
87-
var applicationState = new PersistentComponentState(currentState, new List<PersistComponentStateRegistration>())
101+
var applicationState = new PersistentComponentState(currentState, [])
88102
{
89103
PersistingState = true
90104
};
@@ -101,7 +115,7 @@ public void PersistAsJson_SerializesTheDataToJsonAsync()
101115
{
102116
// Arrange
103117
var currentState = new Dictionary<string, byte[]>();
104-
var applicationState = new PersistentComponentState(currentState, new List<PersistComponentStateRegistration>())
118+
var applicationState = new PersistentComponentState(currentState, [])
105119
{
106120
PersistingState = true
107121
};
@@ -120,7 +134,7 @@ public void PersistAsJson_NullValueAsync()
120134
{
121135
// Arrange
122136
var currentState = new Dictionary<string, byte[]>();
123-
var applicationState = new PersistentComponentState(currentState, new List<PersistComponentStateRegistration>())
137+
var applicationState = new PersistentComponentState(currentState, [])
124138
{
125139
PersistingState = true
126140
};
@@ -140,7 +154,7 @@ public void TryRetrieveFromJson_DeserializesTheDataFromJson()
140154
var myState = new byte[] { 1, 2, 3, 4 };
141155
var serialized = JsonSerializer.SerializeToUtf8Bytes(myState);
142156
var existingState = new Dictionary<string, byte[]>() { ["MyState"] = serialized };
143-
var applicationState = new PersistentComponentState(new Dictionary<string, byte[]>(), new List<PersistComponentStateRegistration>());
157+
var applicationState = new PersistentComponentState(new Dictionary<string, byte[]>(), []);
144158

145159
applicationState.InitializeExistingState(existingState);
146160

@@ -158,7 +172,7 @@ public void TryRetrieveFromJson_NullValue()
158172
// Arrange
159173
var serialized = JsonSerializer.SerializeToUtf8Bytes<byte[]>(null);
160174
var existingState = new Dictionary<string, byte[]>() { ["MyState"] = serialized };
161-
var applicationState = new PersistentComponentState(new Dictionary<string, byte[]>(), new List<PersistComponentStateRegistration>());
175+
var applicationState = new PersistentComponentState(new Dictionary<string, byte[]>(), []);
162176

163177
applicationState.InitializeExistingState(existingState);
164178

0 commit comments

Comments
 (0)
0