Skip to content

Commit 3071509

Browse files
committed
Add test expectations for v3.0.0
1 parent 5058c74 commit 3071509

10 files changed

+314
-0
lines changed

src/Polly.Caching.Memory.NetStandard13.Specs/Polly.Caching.Memory.NetStandard13.Specs.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
<ItemGroup>
1818
<PackageReference Include="FluentAssertions" Version="4.19.3" />
1919
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
20+
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
2021
<PackageReference Include="xunit" Version="2.2.0" />
2122
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
2223

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
4+
namespace Polly.Caching.Memory.Specs.Integration
5+
{
6+
public static class CacheProviderExtensions
7+
{
8+
public static (bool, TResult) TryGet<TResult>(this ISyncCacheProvider<TResult> provider, string key)
9+
{
10+
var fromCache = provider.Get(key);
11+
return (fromCache != null, fromCache);
12+
}
13+
14+
public static async Task<(bool, TResult)> TryGetAsync<TResult>(this IAsyncCacheProvider<TResult> provider, string key, CancellationToken token, bool continueOnCapturedContext)
15+
{
16+
var fromCache = await provider.GetAsync(key, token, continueOnCapturedContext);
17+
return (fromCache != null, fromCache);
18+
}
19+
20+
}
21+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using Xunit;
4+
5+
namespace Polly.Caching.Memory.Specs.Integration
6+
{
7+
public abstract class CacheRoundTripSpecsBase
8+
{
9+
protected CacheRoundTripSpecsBase(ICachePolicyFactory cachePolicyFactory)
10+
{
11+
CachePolicyFactory = cachePolicyFactory;
12+
}
13+
14+
protected ICachePolicyFactory CachePolicyFactory { get; }
15+
16+
protected const string OperationKey = "SomeOperationKey";
17+
18+
public abstract Task Should_roundtrip_this_variant_of<TResult>(TResult testValue);
19+
20+
[Theory]
21+
[MemberData(nameof(SampleClassData))]
22+
public async Task Should_roundtrip_all_variants_of_reference_type(SampleClass testValue)
23+
{
24+
await Should_roundtrip_this_variant_of<SampleClass>(testValue);
25+
}
26+
27+
[Theory]
28+
[MemberData(nameof(SampleStringData))]
29+
public async Task Should_roundtrip_all_variants_of_string(String testValue)
30+
{
31+
await Should_roundtrip_this_variant_of<String>(testValue);
32+
}
33+
34+
[Theory]
35+
[MemberData(nameof(SampleNumericData))]
36+
public async Task Should_roundtrip_all_variants_of_numeric(int testValue)
37+
{
38+
await Should_roundtrip_this_variant_of<int>(testValue);
39+
}
40+
41+
[Theory]
42+
[MemberData(nameof(SampleEnumData))]
43+
public async Task Should_roundtrip_all_variants_of_enum(SampleEnum testValue)
44+
{
45+
await Should_roundtrip_this_variant_of<SampleEnum>(testValue);
46+
}
47+
48+
[Theory]
49+
[MemberData(nameof(SampleBoolData))]
50+
public async Task Should_roundtrip_all_variants_of_bool(bool testValue)
51+
{
52+
await Should_roundtrip_this_variant_of<bool>(testValue);
53+
}
54+
55+
[Theory]
56+
[MemberData(nameof(SampleNullableBoolData))]
57+
public async Task Should_roundtrip_all_variants_of_nullable_bool(bool? testValue)
58+
{
59+
await Should_roundtrip_this_variant_of<bool?>(testValue);
60+
}
61+
62+
public static TheoryData<SampleClass> SampleClassData =>
63+
new TheoryData<SampleClass>
64+
{
65+
new SampleClass(),
66+
new SampleClass()
67+
{
68+
StringProperty = "<html></html>",
69+
IntProperty = 1
70+
},
71+
(SampleClass)null,
72+
default(SampleClass)
73+
};
74+
75+
public static TheoryData<String> SampleStringData =>
76+
new TheoryData<String>
77+
{
78+
"some string",
79+
"",
80+
null,
81+
default(string),
82+
"null"
83+
};
84+
85+
public static TheoryData<int> SampleNumericData =>
86+
new TheoryData<int>
87+
{
88+
-1,
89+
0,
90+
1,
91+
default(int)
92+
};
93+
94+
public static TheoryData<SampleEnum> SampleEnumData =>
95+
new TheoryData<SampleEnum>
96+
{
97+
SampleEnum.FirstValue,
98+
SampleEnum.SecondValue,
99+
default(SampleEnum),
100+
};
101+
102+
public static TheoryData<bool> SampleBoolData =>
103+
new TheoryData<bool>
104+
{
105+
true,
106+
false,
107+
default(bool),
108+
};
109+
110+
public static TheoryData<bool?> SampleNullableBoolData =>
111+
new TheoryData<bool?>
112+
{
113+
true,
114+
false,
115+
null,
116+
default(bool?),
117+
};
118+
119+
public class SampleClass
120+
{
121+
public string StringProperty { get; set; }
122+
public int IntProperty { get; set; }
123+
}
124+
125+
public enum SampleEnum
126+
{
127+
FirstValue,
128+
SecondValue,
129+
}
130+
}
131+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using FluentAssertions;
4+
5+
namespace Polly.Caching.Memory.Specs.Integration
6+
{
7+
public abstract class CacheRoundTripSpecsSyncBase : CacheRoundTripSpecsBase
8+
{
9+
protected CacheRoundTripSpecsSyncBase(ICachePolicyFactory cachePolicyFactory) : base(cachePolicyFactory)
10+
{
11+
}
12+
13+
public override Task Should_roundtrip_this_variant_of<TResult>(TResult testValue)
14+
{
15+
// Arrange
16+
var (cacheProvider, cache) = CachePolicyFactory.CreateSyncCachePolicy<TResult, TResult>();
17+
18+
// Assert - should not be in cache
19+
(bool cacheHit1, TResult fromCache1) = cacheProvider.TryGet(OperationKey);
20+
cacheHit1.Should().BeFalse();
21+
fromCache1.Should().Be(default(TResult));
22+
23+
// Act - should execute underlying delegate and place in cache
24+
int underlyingDelegateExecuteCount = 0;
25+
cache.Execute(ctx =>
26+
{
27+
underlyingDelegateExecuteCount++;
28+
return testValue;
29+
}, new Context(OperationKey))
30+
.ShouldBeEquivalentTo(testValue);
31+
32+
// Assert - should have executed underlying delegate
33+
underlyingDelegateExecuteCount.Should().Be(1);
34+
35+
// Assert - should be in cache
36+
(bool cacheHit2, TResult fromCache2) = cacheProvider.TryGet(OperationKey);
37+
cacheHit2.Should().BeTrue();
38+
fromCache2.ShouldBeEquivalentTo(testValue);
39+
40+
// Act - should execute underlying delegate and place in cache
41+
cache.Execute(ctx =>
42+
{
43+
underlyingDelegateExecuteCount++;
44+
throw new Exception("Cache should be used so this should not get invoked.");
45+
}, new Context(OperationKey))
46+
.ShouldBeEquivalentTo(testValue);
47+
underlyingDelegateExecuteCount.Should().Be(1);
48+
49+
return Task.CompletedTask;
50+
}
51+
}
52+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Polly.Caching.Memory.Specs.Integration
2+
{
3+
public class CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Async : CacheRoundTripSpecsAsyncBase {
4+
public CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Async() : base(new MemoryCachePolicyFactory())
5+
{
6+
}
7+
}
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Polly.Caching.Memory.Specs.Integration
2+
{
3+
public class CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Sync : CacheRoundTripSpecsSyncBase {
4+
public CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Sync() : base(new MemoryCachePolicyFactory())
5+
{
6+
}
7+
}
8+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using FluentAssertions;
5+
6+
namespace Polly.Caching.Memory.Specs.Integration
7+
{
8+
public abstract class CacheRoundTripSpecsAsyncBase : CacheRoundTripSpecsBase
9+
{
10+
protected CacheRoundTripSpecsAsyncBase(ICachePolicyFactory cachePolicyFactory) : base(cachePolicyFactory)
11+
{
12+
}
13+
14+
public override async Task Should_roundtrip_this_variant_of<TResult>(TResult testValue)
15+
{
16+
// Arrange
17+
var (cacheProvider, cache) = CachePolicyFactory.CreateAsyncCachePolicy<TResult, TResult>();
18+
19+
// Assert - should not be in cache
20+
(bool cacheHit1, TResult fromCache1) = await cacheProvider.TryGetAsync(OperationKey, CancellationToken.None, false);
21+
cacheHit1.Should().BeFalse();
22+
fromCache1.Should().Be(default(TResult));
23+
24+
// Act - should execute underlying delegate and place in cache
25+
int underlyingDelegateExecuteCount = 0;
26+
(await cache.ExecuteAsync(ctx =>
27+
{
28+
underlyingDelegateExecuteCount++;
29+
return Task.FromResult(testValue);
30+
}, new Context(OperationKey)))
31+
.ShouldBeEquivalentTo(testValue);
32+
33+
// Assert - should have executed underlying delegate
34+
underlyingDelegateExecuteCount.Should().Be(1);
35+
36+
// Assert - should be in cache
37+
(bool cacheHit2, TResult fromCache2) = await cacheProvider.TryGetAsync(OperationKey, CancellationToken.None, false);
38+
cacheHit2.Should().BeTrue();
39+
fromCache2.ShouldBeEquivalentTo(testValue);
40+
41+
// Act - should execute underlying delegate and place in cache
42+
(await cache.ExecuteAsync(ctx =>
43+
{
44+
underlyingDelegateExecuteCount++;
45+
throw new Exception("Cache should be used so this should not get invoked.");
46+
}, new Context(OperationKey)))
47+
.ShouldBeEquivalentTo(testValue);
48+
underlyingDelegateExecuteCount.Should().Be(1);
49+
}
50+
}
51+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Polly.Caching.Memory.Specs.Integration
2+
{
3+
public interface ICachePolicyFactory
4+
{
5+
(ISyncCacheProvider<TResult>, ISyncPolicy<TResult>) CreateSyncCachePolicy<TCache, TResult>();
6+
(IAsyncCacheProvider<TResult>, IAsyncPolicy<TResult>) CreateAsyncCachePolicy<TCache, TResult>();
7+
}
8+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using Microsoft.Extensions.Caching.Memory;
3+
4+
namespace Polly.Caching.Memory.Specs.Integration
5+
{
6+
public class MemoryCachePolicyFactory : ICachePolicyFactory
7+
{
8+
public (ISyncCacheProvider<TResult>, ISyncPolicy<TResult>) CreateSyncCachePolicy<TCache, TResult>()
9+
{
10+
IMemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());
11+
ISyncCacheProvider<TResult> provider = new MemoryCacheProvider(memoryCache).For<TResult>();
12+
13+
var policy = Policy.Cache<TResult>(provider, TimeSpan.FromHours(1));
14+
return (provider, policy);
15+
}
16+
17+
public (IAsyncCacheProvider<TResult>, IAsyncPolicy<TResult>) CreateAsyncCachePolicy<TCache, TResult>()
18+
{
19+
IMemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());
20+
IAsyncCacheProvider<TResult> provider = new MemoryCacheProvider(memoryCache).AsyncFor<TResult>();
21+
22+
var policy = Policy.CacheAsync<TResult>(provider, TimeSpan.FromHours(1));
23+
return (provider, policy);
24+
}
25+
}
26+
}

src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99
<Import_RootNamespace>Polly.Caching.Memory.Specs</Import_RootNamespace>
1010
</PropertyGroup>
1111
<ItemGroup>
12+
<Compile Include="$(MSBuildThisFileDirectory)Integration\CacheProviderExtensions.cs" />
13+
<Compile Include="$(MSBuildThisFileDirectory)Integration\CacheRoundTripspecsAsyncBase.cs" />
14+
<Compile Include="$(MSBuildThisFileDirectory)Integration\CacheRoundTripSpecsBase.cs" />
15+
<Compile Include="$(MSBuildThisFileDirectory)Integration\CacheRoundTripSpecsSyncBase.cs" />
16+
<Compile Include="$(MSBuildThisFileDirectory)Integration\CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Async.cs" />
17+
<Compile Include="$(MSBuildThisFileDirectory)Integration\CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Sync.cs" />
18+
<Compile Include="$(MSBuildThisFileDirectory)Integration\ICachePolicyFactory.cs" />
19+
<Compile Include="$(MSBuildThisFileDirectory)Integration\MemoryCachePolicyFactory.cs" />
1220
<Compile Include="$(MSBuildThisFileDirectory)Unit\MemoryCacheProviderSpecs.cs" />
1321
</ItemGroup>
1422
</Project>

0 commit comments

Comments
 (0)