Skip to content

Commit d747a00

Browse files
committed
Test written by ai Junie
1 parent 591ec4e commit d747a00

File tree

4 files changed

+111
-14
lines changed

4 files changed

+111
-14
lines changed

Drogecode.Blazor.ExpireStorage.sln.DotSettings.user

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,23 @@
33
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AGenericCache_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fc5dcebce14cd57559452348c3c747aa6c961a8437dd464d765f9aea0d28391_003FGenericCache_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
44
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIJSRuntime_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F21e7e36a5419c3dbaae13e12a7c6b9726b289fcbe33c79ce238feef72f5c1c_003FIJSRuntime_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
55
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AILocalStorageService_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fdfa35791a1dc812b2ccbd8019f39c2d5f39acfaed29f27c75446ab5fea9ec_003FILocalStorageService_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
6+
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALocalStorageOptions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F3f50483ae033e77765dcf47538b74afc20a8c693869319765bbac4cbf8fdcb_003FLocalStorageOptions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
7+
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMemoryCacheServiceCollectionExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F2135d93239e4c6d4e46e64cfb8da4f8eee3abc03028851ff0bb1f6a48a33f_003FMemoryCacheServiceCollectionExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
68
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANotImplementedException_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Ffbcfa522c97815dbbc420ad351b42e6ad55d0d37a9a282d8945a68a707eb_003FNotImplementedException_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
79
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AObject_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F9a6b1457cbcf17db31a383ba49ef9bcc786cf3ef77146d997eee499b27a46d_003FObject_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
810
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AOptionsServiceCollectionExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F24baa99dd8f67b797750aa9e414d3aa0bddac232f5e0cf511c68cb9d1ad1558_003FOptionsServiceCollectionExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
911
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARuntimeHelpers_002ECoreCLR_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fb8d753e12338b313a0baa29e5b7010f685edfd61c8eab6f759541034cc83387_003FRuntimeHelpers_002ECoreCLR_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
12+
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AServiceCollectionExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F6c68988dd163714ce4ffda0caaf82c9f6bf2e3bd1313885cb3765685ab3d_003FServiceCollectionExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
1013
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASR_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F14939830a97c9496242b1664edddd9c7645548bce544534665f26358cfa660_003FSR_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
1114
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATask_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F4d431e535966d3e8d58aed86698f4938fdfbde11da876f5c3a222aa8c29b1_003FTask_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
1215
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATestContext_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fec7777a7fc7c8bea65cca4b05a79bcb24defadab0b5b477a71c1b23745dbe9_003FTestContext_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
1316
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVirtualDispatchHelpers_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F1fe4a1c5fe745590314b4ad86db8c4bc75c255d6ba296a572ee9ddc1a79a6999_003FVirtualDispatchHelpers_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
14-
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=aa718253_002Dbe67_002D4e35_002Dbab4_002D5fdf23f57873/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="MinimalRequestTest" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
17+
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=7ce84f90_002D6ae2_002D4e9e_002D860e_002Deb90f45871f3/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="Junie Session" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
18+
&lt;TestAncestor&gt;&#xD;
19+
&lt;TestId&gt;xUnit::1C862E6B-9B19-0CA3-857C-1CDFA247321F::net10.0::Drogecode.Blazor.ExpireStorage.Tests.Tests.Services.ExpireStorageServiceTests&lt;/TestId&gt;&#xD;
20+
&lt;/TestAncestor&gt;&#xD;
21+
&lt;/SessionState&gt;</s:String>
22+
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=aa718253_002Dbe67_002D4e35_002Dbab4_002D5fdf23f57873/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="MinimalRequestTest" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
1523
&lt;TestAncestor&gt;&#xD;
1624
&lt;TestId&gt;xUnit::1C862E6B-9B19-0CA3-857C-1CDFA247321F::net10.0::Drogecode.Blazor.ExpireStorage.Tests.Tests.Services.ExpireStorageServiceTests&lt;/TestId&gt;&#xD;
1725
&lt;/TestAncestor&gt;&#xD;

Tests/Drogecode.Blazor.ExpireStorage.Tests/Mocks/LocalStorageServiceMock.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ public LocalStorageServiceMock(IMemoryCache memoryCache)
1818

1919
public async ValueTask<T?> GetItemAsync<T>(string key, CancellationToken cancellationToken = new CancellationToken())
2020
{
21-
if (_memoryCache.TryGetValue(key, out var value))
21+
if (_memoryCache.TryGetValue(key, out object? value))
2222
{
23-
return (T)value!;
23+
if (value is null) return default;
24+
// The value in cache is likely ExpiryStorageModel<T>
25+
try { return (T)value; } catch { return default; }
2426
}
2527
return default;
2628
}
@@ -52,7 +54,7 @@ public LocalStorageServiceMock(IMemoryCache memoryCache)
5254

5355
public async ValueTask RemoveItemAsync(string key, CancellationToken cancellationToken = new CancellationToken())
5456
{
55-
throw new NotImplementedException();
57+
_memoryCache.Remove(key);
5658
}
5759

5860
public async ValueTask RemoveItemsAsync(IEnumerable<string> keys, CancellationToken cancellationToken = new CancellationToken())

Tests/Drogecode.Blazor.ExpireStorage.Tests/Mocks/SessionStorageServiceMock.cs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,39 @@
11
using Blazored.SessionStorage;
2+
using Microsoft.Extensions.Caching.Memory;
23

34
namespace Drogecode.Blazor.ExpireStorage.Tests.Mocks;
45

56
public class SessionStorageServiceMock : ISessionStorageService
67
{
8+
private readonly IMemoryCache _memoryCache;
9+
10+
public SessionStorageServiceMock(IMemoryCache memoryCache)
11+
{
12+
_memoryCache = memoryCache;
13+
}
14+
715
public async ValueTask ClearAsync(CancellationToken cancellationToken = new CancellationToken())
816
{
917
throw new NotImplementedException();
1018
}
1119

12-
public async ValueTask<T> GetItemAsync<T>(string key, CancellationToken cancellationToken = new CancellationToken())
20+
public async ValueTask<T?> GetItemAsync<T>(string key, CancellationToken cancellationToken = new CancellationToken())
1321
{
14-
throw new NotImplementedException();
22+
if (_memoryCache.TryGetValue($"session_{key}", out object? value))
23+
{
24+
if (value is null) return default;
25+
// The value in cache is likely ExpiryStorageModel<T>
26+
try { return (T)value; } catch { return default; }
27+
}
28+
return default;
1529
}
1630

17-
public async ValueTask<string> GetItemAsStringAsync(string key, CancellationToken cancellationToken = new CancellationToken())
31+
public async ValueTask<string?> GetItemAsStringAsync(string key, CancellationToken cancellationToken = new CancellationToken())
1832
{
1933
throw new NotImplementedException();
2034
}
2135

22-
public async ValueTask<string> KeyAsync(int index, CancellationToken cancellationToken = new CancellationToken())
36+
public async ValueTask<string?> KeyAsync(int index, CancellationToken cancellationToken = new CancellationToken())
2337
{
2438
throw new NotImplementedException();
2539
}
@@ -41,7 +55,7 @@ public class SessionStorageServiceMock : ISessionStorageService
4155

4256
public async ValueTask RemoveItemAsync(string key, CancellationToken cancellationToken = new CancellationToken())
4357
{
44-
throw new NotImplementedException();
58+
_memoryCache.Remove($"session_{key}");
4559
}
4660

4761
public async ValueTask RemoveItemsAsync(IEnumerable<string> keys, CancellationToken cancellationToken = new CancellationToken())
@@ -51,7 +65,8 @@ public class SessionStorageServiceMock : ISessionStorageService
5165

5266
public async ValueTask SetItemAsync<T>(string key, T data, CancellationToken cancellationToken = new CancellationToken())
5367
{
54-
throw new NotImplementedException();
68+
System.Console.WriteLine($"[DEBUG_LOG] SessionStorage SetItem: {key} type: {typeof(T)}");
69+
_memoryCache.Set($"session_{key}", data);
5570
}
5671

5772
public async ValueTask SetItemAsStringAsync(string key, string data, CancellationToken cancellationToken = new CancellationToken())

Tests/Drogecode.Blazor.ExpireStorage.Tests/Tests/Services/ExpireStorageServiceTests.cs

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,29 @@
22

33
namespace Drogecode.Blazor.ExpireStorage.Tests.Tests.Services;
44

5-
public class ExpireStorageServiceTests
5+
public class ExpireStorageServiceTests : IDisposable
66
{
77
private readonly IExpireStorageService _expireStorageService;
88

99
public ExpireStorageServiceTests(IExpireStorageService expireStorageService)
1010
{
1111
_expireStorageService = expireStorageService;
12+
ExpireStorageService.LogToConsole = true;
13+
}
14+
15+
public void Dispose()
16+
{
17+
ExpireStorageService.Postfix = null;
18+
ExpireStorageService.LogToConsole = false;
19+
// We can't easily reset IsOffline because it has a private setter and no public reset method,
20+
// but we can trigger it to be false by a successful request.
1221
}
1322

1423
[Fact]
1524
public async Task MinimalRequestTest()
1625
{
1726
const string cacheKey = "MinimalRequestTest";
18-
var response = await _expireStorageService.CachedRequestAsync<string>(cacheKey, () => Task.FromResult("test"), clt: TestContext.Current.CancellationToken);
27+
var response = await _expireStorageService.CachedRequestAsync<string>(cacheKey, () => Task.FromResult("test"), new CachedRequest { ExpireLocalStorage = DateTime.UtcNow.AddDays(7) }, clt: TestContext.Current.CancellationToken);
1928
Assert.NotNull(response);
2029
response.Should().Be("test");
2130
}
@@ -27,7 +36,7 @@ public async Task ByFunctionTest()
2736
var response = await _expireStorageService.CachedRequestAsync<TestStringResponse>(cacheKey, () => Task.FromResult(new TestStringResponse
2837
{
2938
Data = "test"
30-
}), clt: TestContext.Current.CancellationToken);
39+
}), new CachedRequest { ExpireLocalStorage = DateTime.UtcNow.AddDays(7) }, clt: TestContext.Current.CancellationToken);
3140
Assert.NotNull(response?.Data);
3241
response.HandledBy.Should().Be(HandledBy.Function);
3342
response.Data.Should().Be("test");
@@ -41,17 +50,80 @@ public async Task FromCacheTest()
4150
{
4251
Data = "test"
4352
}),
53+
new CachedRequest { ExpireLocalStorage = DateTime.UtcNow.AddDays(7) },
4454
clt: TestContext.Current.CancellationToken);
4555
Assert.NotNull(addToCache?.Data);
4656
addToCache.HandledBy.Should().Be(HandledBy.Function);
4757
var response = await _expireStorageService.CachedRequestAsync<TestStringResponse>(cacheKey, () => Task.FromResult(new TestStringResponse
4858
{
4959
Data = "not called"
5060
}),
51-
new CachedRequest { OneCallPerCache = true },
61+
new CachedRequest { OneCallPerCache = true, ExpireLocalStorage = DateTime.UtcNow.AddDays(7) },
5262
clt: TestContext.Current.CancellationToken);
5363
Assert.NotNull(response?.Data);
5464
response.HandledBy.Should().Be(HandledBy.Cache);
5565
response.Data.Should().Be("test");
5666
}
67+
68+
[Fact]
69+
public async Task PostfixTest()
70+
{
71+
const string cacheKey = "PostfixTest";
72+
ExpireStorageService.Postfix = "user1";
73+
await _expireStorageService.CachedRequestAsync<TestStringResponse>(cacheKey, () => Task.FromResult(new TestStringResponse { Data = "data1" }), new CachedRequest { ExpireLocalStorage = DateTime.UtcNow.AddDays(7) }, clt: TestContext.Current.CancellationToken);
74+
75+
ExpireStorageService.Postfix = "user2";
76+
var response2 = await _expireStorageService.CachedRequestAsync<TestStringResponse>(cacheKey, () => Task.FromResult(new TestStringResponse { Data = "data2" }), new CachedRequest { ExpireLocalStorage = DateTime.UtcNow.AddDays(7) }, clt: TestContext.Current.CancellationToken);
77+
78+
Assert.NotNull(response2?.Data);
79+
response2.Data.Should().Be("data2");
80+
response2.HandledBy.Should().Be(HandledBy.Function);
81+
82+
ExpireStorageService.Postfix = "user1";
83+
var response1FromCache = await _expireStorageService.CachedRequestAsync<TestStringResponse>(cacheKey, () => Task.FromResult(new TestStringResponse { Data = "not called" }), new CachedRequest { OneCallPerCache = true, ExpireLocalStorage = DateTime.UtcNow.AddDays(7) }, clt: TestContext.Current.CancellationToken);
84+
Assert.NotNull(response1FromCache?.Data);
85+
response1FromCache.Data.Should().Be("data1");
86+
response1FromCache.HandledBy.Should().Be(HandledBy.Cache);
87+
}
88+
89+
[Fact]
90+
public async Task IgnoreCacheTest()
91+
{
92+
const string cacheKey = "IgnoreCacheTest";
93+
await _expireStorageService.CachedRequestAsync<TestStringResponse>(cacheKey, () => Task.FromResult(new TestStringResponse { Data = "cached" }), new CachedRequest { OneCallPerCache = true, ExpireLocalStorage = DateTime.UtcNow.AddDays(7) }, clt: TestContext.Current.CancellationToken);
94+
95+
var response = await _expireStorageService.CachedRequestAsync<TestStringResponse>(cacheKey, () => Task.FromResult(new TestStringResponse { Data = "fresh" }), new CachedRequest { IgnoreCache = true }, clt: TestContext.Current.CancellationToken);
96+
Assert.NotNull(response?.Data);
97+
response.Data.Should().Be("fresh");
98+
response.HandledBy.Should().Be(HandledBy.Function);
99+
}
100+
101+
[Fact]
102+
public async Task HttpRequestExceptionSetsOfflineTest()
103+
{
104+
const string cacheKey = "OfflineTest";
105+
try
106+
{
107+
await _expireStorageService.CachedRequestAsync<TestStringResponse>(cacheKey, () => throw new HttpRequestException(), new CachedRequest { ExpireLocalStorage = DateTime.UtcNow.AddDays(7) }, clt: TestContext.Current.CancellationToken);
108+
}
109+
catch (HttpRequestException) { }
110+
111+
ExpireStorageService.IsOffline.Should().BeTrue();
112+
113+
// Recover
114+
await _expireStorageService.CachedRequestAsync<TestStringResponse>(cacheKey, () => Task.FromResult(new TestStringResponse { Data = "recovered" }), new CachedRequest { ExpireLocalStorage = DateTime.UtcNow.AddDays(7) }, clt: TestContext.Current.CancellationToken);
115+
ExpireStorageService.IsOffline.Should().BeFalse();
116+
}
117+
118+
[Fact]
119+
public async Task CancellationTokenTest()
120+
{
121+
const string cacheKey = "CancellationTokenTest";
122+
using var cts = new CancellationTokenSource();
123+
cts.Cancel();
124+
125+
var response = await _expireStorageService.CachedRequestAsync<TestStringResponse>(cacheKey, () => Task.FromResult(new TestStringResponse { Data = "test" }), clt: cts.Token);
126+
127+
response.Should().BeNull();
128+
}
57129
}

0 commit comments

Comments
 (0)