Skip to content

Commit

Permalink
Replace Moq with NSubstitute (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
Turnerj authored Aug 10, 2023
1 parent aee3db3 commit 8f5956b
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 149 deletions.
20 changes: 10 additions & 10 deletions tests/CacheTower.Tests/CacheStackTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Threading.Tasks;
using CacheTower.Providers.Memory;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using NSubstitute;

namespace CacheTower.Tests
{
Expand Down Expand Up @@ -83,13 +83,13 @@ public async Task Evict_EvictsAllTheLayers()
[TestMethod]
public async Task Evict_TriggersCacheChangeExtension()
{
var mockExtension = new Mock<ICacheChangeExtension>();
await using var cacheStack = new CacheStack(null, new(new[] { new MemoryCacheLayer() }) { Extensions = new[] { mockExtension.Object } });
var mockExtension = Substitute.For<ICacheChangeExtension>();
await using var cacheStack = new CacheStack(null, new(new[] { new MemoryCacheLayer() }) { Extensions = new[] { mockExtension } });
var cacheEntry = await cacheStack.SetAsync("Evict_TriggerCacheChangeExtension", 42, TimeSpan.FromDays(1));

await cacheStack.EvictAsync("Evict_TriggerCacheChangeExtension");

mockExtension.Verify(e => e.OnCacheEvictionAsync("Evict_TriggerCacheChangeExtension"), Times.Once);
await mockExtension.Received(1).OnCacheEvictionAsync("Evict_TriggerCacheChangeExtension");
}
[TestMethod, ExpectedException(typeof(ObjectDisposedException))]
public async Task Evict_ThrowsOnUseAfterDisposal()
Expand Down Expand Up @@ -122,12 +122,12 @@ public async Task Flush_FlushesAllTheLayers()
[TestMethod]
public async Task Flush_TriggersCacheChangeExtension()
{
var mockExtension = new Mock<ICacheChangeExtension>();
await using var cacheStack = new CacheStack(null, new(new[] { new MemoryCacheLayer() }) { Extensions = new[] { mockExtension.Object } });
var mockExtension = Substitute.For<ICacheChangeExtension>();
await using var cacheStack = new CacheStack(null, new(new[] { new MemoryCacheLayer() }) { Extensions = new[] { mockExtension } });

await cacheStack.FlushAsync();

mockExtension.Verify(e => e.OnCacheFlushAsync(), Times.Once);
await mockExtension.Received(1).OnCacheFlushAsync();
}
[TestMethod, ExpectedException(typeof(ObjectDisposedException))]
public async Task Flush_ThrowsOnUseAfterDisposal()
Expand Down Expand Up @@ -201,11 +201,11 @@ public async Task Set_SetsAllTheLayers()
[TestMethod]
public async Task Set_TriggersCacheChangeExtension()
{
var mockExtension = new Mock<ICacheChangeExtension>();
await using var cacheStack = new CacheStack(null, new(new[] { new MemoryCacheLayer() }) { Extensions = new[] { mockExtension.Object } });
var mockExtension = Substitute.For<ICacheChangeExtension>();
await using var cacheStack = new CacheStack(null, new(new[] { new MemoryCacheLayer() }) { Extensions = new[] { mockExtension } });
var cacheEntry = await cacheStack.SetAsync("Set_TriggersCacheChangeExtension", 42, TimeSpan.FromDays(1));

mockExtension.Verify(e => e.OnCacheUpdateAsync("Set_TriggersCacheChangeExtension", cacheEntry.Expiry, CacheUpdateType.AddOrUpdateEntry), Times.Once);
await mockExtension.Received(1).OnCacheUpdateAsync("Set_TriggersCacheChangeExtension", cacheEntry.Expiry, CacheUpdateType.AddOrUpdateEntry);
}

[TestMethod, ExpectedException(typeof(ArgumentNullException))]
Expand Down
2 changes: 1 addition & 1 deletion tests/CacheTower.Tests/CacheTower.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.0" />
<PackageReference Include="Moq" Version="4.18.1" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
<PackageReference Include="coverlet.collector" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.3" />
<PackageReference Include="NSubstitute" Version="5.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
15 changes: 8 additions & 7 deletions tests/CacheTower.Tests/Extensions/AutoCleanupExtensionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
using CacheTower.Extensions;
using CacheTower.Providers.Memory;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using NSubstitute;
using NSubstitute.ReceivedExtensions;

namespace CacheTower.Tests.Extensions
{
Expand All @@ -34,20 +35,20 @@ public async Task ThrowForRegisteringTwoCacheStacks()
public async Task RunsBackgroundCleanup()
{
await using var extension = new AutoCleanupExtension(TimeSpan.FromMilliseconds(500));
var cacheStackMock = new Mock<ICacheStack>();
extension.Register(cacheStackMock.Object);
var cacheStackMock = Substitute.For<ICacheStack>();
extension.Register(cacheStackMock);
await Task.Delay(TimeSpan.FromSeconds(2));
cacheStackMock.Verify(c => c.CleanupAsync(), Times.AtLeast(2));
await cacheStackMock.Received(Quantity.Within(2, int.MaxValue)).CleanupAsync();
}

[TestMethod]
public async Task BackgroundCleanupObeysCancel()
{
await using var extension = new AutoCleanupExtension(TimeSpan.FromMilliseconds(500), new CancellationToken(true));
var cacheStackMock = new Mock<ICacheStack>();
extension.Register(cacheStackMock.Object);
var cacheStackMock = Substitute.For<ICacheStack>();
extension.Register(cacheStackMock);
await Task.Delay(TimeSpan.FromSeconds(2));
cacheStackMock.Verify(c => c.CleanupAsync(), Times.Never);
await cacheStackMock.DidNotReceive().CleanupAsync();
}
}
}
62 changes: 25 additions & 37 deletions tests/CacheTower.Tests/Extensions/ExtensionContainerTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CacheTower.Extensions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using NSubstitute;

namespace CacheTower.Tests.Extensions
{
Expand All @@ -27,76 +24,67 @@ public async Task AcceptsEmptyExtensions()
[TestMethod]
public async Task DistributedLockExtension()
{
var cacheStackMock = new Mock<ICacheStack>();
var distributedLockMock = new Mock<IDistributedLockExtension>();
await using var container = new ExtensionContainer(new[] { distributedLockMock.Object });
var cacheStackMock = Substitute.For<ICacheStack>();
var distributedLockMock = Substitute.For<IDistributedLockExtension>();
await using var container = new ExtensionContainer(new[] { distributedLockMock });

container.Register(cacheStackMock.Object);
container.Register(cacheStackMock);

var distributedLock = await container.AwaitAccessAsync("DistributedLockCacheKey");

distributedLockMock.Verify(e => e.Register(cacheStackMock.Object), Times.Once);
distributedLockMock.Verify(e => e.AwaitAccessAsync("DistributedLockCacheKey"), Times.Once);
distributedLockMock.Received(1).Register(cacheStackMock);
await distributedLockMock.Received(1).AwaitAccessAsync("DistributedLockCacheKey");
}

[TestMethod]
public async Task CacheChangeExtension_Update()
{
var cacheStackMock = new Mock<ICacheStack>();
var valueRefreshMock = new Mock<ICacheChangeExtension>();
await using var container = new ExtensionContainer(new[] { valueRefreshMock.Object });
var cacheStackMock = Substitute.For<ICacheStack>();
var valueRefreshMock = Substitute.For<ICacheChangeExtension>();
await using var container = new ExtensionContainer(new[] { valueRefreshMock });

container.Register(cacheStackMock.Object);
container.Register(cacheStackMock);

var expiry = DateTime.UtcNow.AddDays(1);

await container.OnCacheUpdateAsync("CacheChangeKey", expiry, CacheUpdateType.AddEntry);

valueRefreshMock.Verify(e => e.Register(cacheStackMock.Object), Times.Once);
valueRefreshMock.Verify(e =>
e.OnCacheUpdateAsync("CacheChangeKey", expiry, CacheUpdateType.AddEntry),
Times.Once
);
valueRefreshMock.Received(1).Register(cacheStackMock);
await valueRefreshMock.Received(1).OnCacheUpdateAsync("CacheChangeKey", expiry, CacheUpdateType.AddEntry);
}

[TestMethod]
public async Task CacheChangeExtension_Eviction()
{
var cacheStackMock = new Mock<ICacheStack>();
var valueRefreshMock = new Mock<ICacheChangeExtension>();
await using var container = new ExtensionContainer(new[] { valueRefreshMock.Object });
var cacheStackMock = Substitute.For<ICacheStack>();
var valueRefreshMock = Substitute.For<ICacheChangeExtension>();
await using var container = new ExtensionContainer(new[] { valueRefreshMock });

container.Register(cacheStackMock.Object);
container.Register(cacheStackMock);

var expiry = DateTime.UtcNow.AddDays(1);

await container.OnCacheEvictionAsync("CacheChangeKey");

valueRefreshMock.Verify(e => e.Register(cacheStackMock.Object), Times.Once);
valueRefreshMock.Verify(e =>
e.OnCacheEvictionAsync("CacheChangeKey"),
Times.Once
);
valueRefreshMock.Received(1).Register(cacheStackMock);
await valueRefreshMock.Received(1).OnCacheEvictionAsync("CacheChangeKey");
}

[TestMethod]
public async Task CacheChangeExtension_Flush()
{
var cacheStackMock = new Mock<ICacheStack>();
var valueRefreshMock = new Mock<ICacheChangeExtension>();
await using var container = new ExtensionContainer(new[] { valueRefreshMock.Object });
var cacheStackMock = Substitute.For<ICacheStack>();
var valueRefreshMock = Substitute.For<ICacheChangeExtension>();
await using var container = new ExtensionContainer(new[] { valueRefreshMock });

container.Register(cacheStackMock.Object);
container.Register(cacheStackMock);

var expiry = DateTime.UtcNow.AddDays(1);

await container.OnCacheFlushAsync();

valueRefreshMock.Verify(e => e.Register(cacheStackMock.Object), Times.Once);
valueRefreshMock.Verify(e =>
e.OnCacheFlushAsync(),
Times.Once
);
valueRefreshMock.Received(1).Register(cacheStackMock);
await valueRefreshMock.Received(1).OnCacheFlushAsync();
}
}
}
24 changes: 12 additions & 12 deletions tests/CacheTower.Tests/Extensions/Redis/RedisLockExtensionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using CacheTower.Extensions.Redis;
using CacheTower.Tests.Utils;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using NSubstitute;
using StackExchange.Redis;

namespace CacheTower.Tests.Extensions.Redis;
Expand Down Expand Up @@ -33,7 +33,7 @@ public void ThrowForNullChannel()
public void ThrowForRegisteringTwoCacheStacks()
{
var extension = new RedisLockExtension(RedisHelper.GetConnection());
var cacheStack = new Mock<ICacheStack>().Object;
var cacheStack = Substitute.For<ICacheStack>();
extension.Register(cacheStack);
extension.Register(cacheStack);
}
Expand Down Expand Up @@ -68,9 +68,9 @@ public async Task RefreshValueNotifiesChannelSubscribers()

var connection = RedisHelper.GetConnection();

var cacheStackMock = new Mock<ICacheStack>();
var cacheStackMock = Substitute.For<ICacheStack>();
var extension = new RedisLockExtension(connection, RedisLockOptions.Default);
extension.Register(cacheStackMock.Object);
extension.Register(cacheStackMock);

var completionSource = new TaskCompletionSource<bool>();

Expand Down Expand Up @@ -112,9 +112,9 @@ public async Task ObservedLockSingle()

var connection = RedisHelper.GetConnection();

var cacheStackMock = new Mock<ICacheStack>();
var cacheStackMock = Substitute.For<ICacheStack>();
var extension = new RedisLockExtension(connection, RedisLockOptions.Default);
extension.Register(cacheStackMock.Object);
extension.Register(cacheStackMock);

//Establish lock
await connection.GetDatabase().StringSetAsync("Lock:TestKey", RedisValue.EmptyString);
Expand Down Expand Up @@ -143,9 +143,9 @@ public async Task ObservedLockMultiple()

var connection = RedisHelper.GetConnection();

var cacheStackMock = new Mock<ICacheStack>();
var cacheStackMock = Substitute.For<ICacheStack>();
var extension = new RedisLockExtension(connection, RedisLockOptions.Default);
extension.Register(cacheStackMock.Object);
extension.Register(cacheStackMock);

//Establish lock
await connection.GetDatabase().StringSetAsync("Lock:TestKey", RedisValue.EmptyString);
Expand Down Expand Up @@ -178,9 +178,9 @@ public async Task FailsafeOnSubscriberFailure()

var connection = RedisHelper.GetConnection();

var cacheStackMock = new Mock<ICacheStack>();
var cacheStackMock = Substitute.For<ICacheStack>();
var extension = new RedisLockExtension(connection, RedisLockOptions.Default with { LockTimeout = TimeSpan.FromSeconds(1) });
extension.Register(cacheStackMock.Object);
extension.Register(cacheStackMock);

//Establish lock
await connection.GetDatabase().StringSetAsync("Lock:TestKey", RedisValue.EmptyString);
Expand Down Expand Up @@ -212,9 +212,9 @@ public async Task BusyLockCheckWorksWhenSubscriberFails()

var connection = RedisHelper.GetConnection();

var cacheStackMock = new Mock<ICacheStack>();
var cacheStackMock = Substitute.For<ICacheStack>();
var extension = new RedisLockExtension(connection, RedisLockOptions.Default with { LockCheckStrategy = LockCheckStrategy.WithSpinLock(TimeSpan.FromMilliseconds(50)) });
extension.Register(cacheStackMock.Object);
extension.Register(cacheStackMock);

//Establish lock
await connection.GetDatabase().StringSetAsync("Lock:TestKey", RedisValue.EmptyString);
Expand Down
Loading

0 comments on commit 8f5956b

Please sign in to comment.