From a00fbc6a546ce212adab088b1af9f909fe7df9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 13 Aug 2023 14:48:57 +0800 Subject: [PATCH 1/2] test: replace moq with nsubstitute --- .../EventBusOptions.cs | 2 - ....Ddd.Infrastructure.EntityFramework.csproj | 2 +- ...itecture.Ddd.Infrastructure.MongoDb.csproj | 2 +- ...blogs.Architecture.IntegrationTests.csproj | 2 +- .../IntegrationEventPublishTests.cs | 51 +++--- .../Cnblogs.Architecture.TestShared.csproj | 2 +- .../Cnblogs.Architecture.UnitTests.csproj | 2 +- .../Cqrs/Behaviors/CacheBehaviorTests.cs | 70 ++++---- .../Cqrs/Behaviors/LoggerBehaviorTests.cs | 61 +++++-- .../Cqrs/FakeObjects/CacheMockExtensions.cs | 21 +-- .../InvalidCacheRequestHandlerTests.cs | 50 +++--- .../EntityFramework/BaseRepositoryTests.cs | 93 +++++----- .../FakeObjects/FakeMongoDbContext.cs | 42 +++-- .../FakeObjects/TestMongoRepository.cs | 12 +- .../MongoDb/MongoBaseRepositoryTests.cs | 160 ++++++++---------- test/Directory.Build.props | 17 +- 16 files changed, 292 insertions(+), 297 deletions(-) diff --git a/src/Cnblogs.Architecture.Ddd.EventBus.Abstractions/EventBusOptions.cs b/src/Cnblogs.Architecture.Ddd.EventBus.Abstractions/EventBusOptions.cs index de32368..e4756d1 100644 --- a/src/Cnblogs.Architecture.Ddd.EventBus.Abstractions/EventBusOptions.cs +++ b/src/Cnblogs.Architecture.Ddd.EventBus.Abstractions/EventBusOptions.cs @@ -1,5 +1,3 @@ -using Microsoft.Extensions.DependencyInjection; - namespace Cnblogs.Architecture.Ddd.EventBus.Abstractions; /// diff --git a/src/Cnblogs.Architecture.Ddd.Infrastructure.EntityFramework/Cnblogs.Architecture.Ddd.Infrastructure.EntityFramework.csproj b/src/Cnblogs.Architecture.Ddd.Infrastructure.EntityFramework/Cnblogs.Architecture.Ddd.Infrastructure.EntityFramework.csproj index 35bf55a..a49f39d 100644 --- a/src/Cnblogs.Architecture.Ddd.Infrastructure.EntityFramework/Cnblogs.Architecture.Ddd.Infrastructure.EntityFramework.csproj +++ b/src/Cnblogs.Architecture.Ddd.Infrastructure.EntityFramework/Cnblogs.Architecture.Ddd.Infrastructure.EntityFramework.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/Cnblogs.Architecture.Ddd.Infrastructure.MongoDb/Cnblogs.Architecture.Ddd.Infrastructure.MongoDb.csproj b/src/Cnblogs.Architecture.Ddd.Infrastructure.MongoDb/Cnblogs.Architecture.Ddd.Infrastructure.MongoDb.csproj index 380b412..d0f7906 100644 --- a/src/Cnblogs.Architecture.Ddd.Infrastructure.MongoDb/Cnblogs.Architecture.Ddd.Infrastructure.MongoDb.csproj +++ b/src/Cnblogs.Architecture.Ddd.Infrastructure.MongoDb/Cnblogs.Architecture.Ddd.Infrastructure.MongoDb.csproj @@ -10,7 +10,7 @@ - + diff --git a/test/Cnblogs.Architecture.IntegrationTests/Cnblogs.Architecture.IntegrationTests.csproj b/test/Cnblogs.Architecture.IntegrationTests/Cnblogs.Architecture.IntegrationTests.csproj index a950386..6414d25 100644 --- a/test/Cnblogs.Architecture.IntegrationTests/Cnblogs.Architecture.IntegrationTests.csproj +++ b/test/Cnblogs.Architecture.IntegrationTests/Cnblogs.Architecture.IntegrationTests.csproj @@ -1,7 +1,7 @@ - + diff --git a/test/Cnblogs.Architecture.IntegrationTests/IntegrationEventPublishTests.cs b/test/Cnblogs.Architecture.IntegrationTests/IntegrationEventPublishTests.cs index b0bd4c7..664d29a 100644 --- a/test/Cnblogs.Architecture.IntegrationTests/IntegrationEventPublishTests.cs +++ b/test/Cnblogs.Architecture.IntegrationTests/IntegrationEventPublishTests.cs @@ -8,7 +8,8 @@ using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using Moq; +using NSubstitute; +using NSubstitute.ExceptionExtensions; namespace Cnblogs.Architecture.IntegrationTests; @@ -20,13 +21,13 @@ public async Task EventBus_PublishEvent_SuccessAsync() // Arrange const string data = "hello"; var builder = new WebApplicationFactory(); - var eventBusMock = new Mock(); + var eventBusMock = Substitute.For(); builder = builder.WithWebHostBuilder( b => b.ConfigureServices( services => { services.RemoveAll(); - services.AddScoped(_ => eventBusMock.Object); + services.AddScoped(_ => eventBusMock); })); // Act @@ -39,9 +40,9 @@ public async Task EventBus_PublishEvent_SuccessAsync() // Assert response.Should().BeSuccessful(); content.Should().BeNullOrEmpty(); - eventBusMock.Verify( - x => x.PublishAsync(It.IsAny(), It.Is(t => t.Message == data)), - Times.Once); + await eventBusMock.Received(1).PublishAsync( + Arg.Any(), + Arg.Is(t => t.Message == data)); } [Fact] @@ -50,13 +51,13 @@ public async Task EventBus_Downgrading_DowngradeAsync() // Arrange const string data = "hello"; var builder = new WebApplicationFactory(); - var eventBusMock = new Mock(); + var eventBusMock = Substitute.For(); builder = builder.WithWebHostBuilder( b => b.ConfigureServices( services => { services.RemoveAll(); - services.AddScoped(_ => eventBusMock.Object); + services.AddScoped(_ => eventBusMock); services.Configure( o => { @@ -64,7 +65,7 @@ public async Task EventBus_Downgrading_DowngradeAsync() o.DowngradeInterval = 3000; }); })); - eventBusMock.Setup(x => x.PublishAsync(It.IsAny(), It.IsAny())) + eventBusMock.PublishAsync(Arg.Any(), Arg.Any()) .ThrowsAsync(new InvalidOperationException()); // Act @@ -77,9 +78,9 @@ public async Task EventBus_Downgrading_DowngradeAsync() // Assert response.Should().BeSuccessful(); content.Should().BeNullOrEmpty(); - eventBusMock.Verify( - x => x.PublishAsync(It.IsAny(), It.Is(t => t.Message == data)), - Times.Exactly(2)); + await eventBusMock.Received(2).PublishAsync( + Arg.Any(), + Arg.Is(t => t.Message == data)); } [Fact] @@ -88,13 +89,13 @@ public async Task EventBus_MaximumBufferSizeReached_ThrowAsync() // Arrange const string data = "hello"; var builder = new WebApplicationFactory(); - var eventBusMock = new Mock(); + var eventBusMock = Substitute.For(); builder = builder.WithWebHostBuilder( b => b.ConfigureServices( services => { services.RemoveAll(); - services.AddScoped(_ => eventBusMock.Object); + services.AddScoped(_ => eventBusMock); services.Configure( o => { @@ -103,7 +104,7 @@ public async Task EventBus_MaximumBufferSizeReached_ThrowAsync() o.DowngradeInterval = 3000; }); })); - eventBusMock.Setup(x => x.PublishAsync(It.IsAny(), It.IsAny())) + eventBusMock.PublishAsync(Arg.Any(), Arg.Any()) .ThrowsAsync(new InvalidOperationException()); var client = builder.CreateClient(); await client.PostAsJsonAsync( @@ -123,13 +124,13 @@ public async Task EventBus_MaximumBatchSize_OneBatchAsync() // Arrange const string data = "hello"; var builder = new WebApplicationFactory(); - var eventBusMock = new Mock(); + var eventBusMock = Substitute.For(); builder = builder.WithWebHostBuilder( b => b.ConfigureServices( services => { services.RemoveAll(); - services.AddScoped(_ => eventBusMock.Object); + services.AddScoped(_ => eventBusMock); services.Configure( o => { @@ -149,7 +150,7 @@ public async Task EventBus_MaximumBatchSize_OneBatchAsync() await Task.Delay(1000); // Assert - eventBusMock.Verify(x => x.PublishAsync(It.IsAny(), It.IsAny()), Times.Once); + await eventBusMock.Received(1).PublishAsync(Arg.Any(), Arg.Any()); } [Fact] @@ -158,13 +159,13 @@ public async Task EventBus_DowngradeThenRecover_RecoverAsync() // Arrange const string data = "hello"; var builder = new WebApplicationFactory(); - var eventBusMock = new Mock(); + var eventBusMock = Substitute.For(); builder = builder.WithWebHostBuilder( b => b.ConfigureServices( services => { services.RemoveAll(); - services.AddScoped(_ => eventBusMock.Object); + services.AddScoped(_ => eventBusMock); services.Configure( o => { @@ -172,7 +173,7 @@ public async Task EventBus_DowngradeThenRecover_RecoverAsync() o.DowngradeInterval = 4000; }); })); - eventBusMock.Setup(x => x.PublishAsync(It.IsAny(), It.IsAny())) + eventBusMock.PublishAsync(Arg.Any(), Arg.Any()) .ThrowsAsync(new InvalidOperationException()); await builder.CreateClient().PostAsJsonAsync( "/api/v1/strings", @@ -180,7 +181,8 @@ await builder.CreateClient().PostAsJsonAsync( await Task.Delay(1000); // failed, now it is downgraded // Act - eventBusMock.Reset(); + eventBusMock.PublishAsync(Arg.Any(), Arg.Any()).Returns(Task.CompletedTask); + eventBusMock.ClearReceivedCalls(); await Task.Delay(2000); // recover await builder.CreateClient().PostAsJsonAsync( "/api/v1/strings", @@ -188,8 +190,7 @@ await builder.CreateClient().PostAsJsonAsync( await Task.Delay(1000); // Assert - eventBusMock.Verify( - x => x.PublishAsync(It.IsAny(), It.Is(t => t.Message == data)), - Times.Exactly(2)); + await eventBusMock.Received(2) + .PublishAsync(Arg.Any(), Arg.Is(t => t.Message == data)); } } diff --git a/test/Cnblogs.Architecture.TestShared/Cnblogs.Architecture.TestShared.csproj b/test/Cnblogs.Architecture.TestShared/Cnblogs.Architecture.TestShared.csproj index 714a257..6693d4e 100644 --- a/test/Cnblogs.Architecture.TestShared/Cnblogs.Architecture.TestShared.csproj +++ b/test/Cnblogs.Architecture.TestShared/Cnblogs.Architecture.TestShared.csproj @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/test/Cnblogs.Architecture.UnitTests/Cnblogs.Architecture.UnitTests.csproj b/test/Cnblogs.Architecture.UnitTests/Cnblogs.Architecture.UnitTests.csproj index 33643fb..475068a 100644 --- a/test/Cnblogs.Architecture.UnitTests/Cnblogs.Architecture.UnitTests.csproj +++ b/test/Cnblogs.Architecture.UnitTests/Cnblogs.Architecture.UnitTests.csproj @@ -1,7 +1,7 @@ - + diff --git a/test/Cnblogs.Architecture.UnitTests/Cqrs/Behaviors/CacheBehaviorTests.cs b/test/Cnblogs.Architecture.UnitTests/Cqrs/Behaviors/CacheBehaviorTests.cs index a80151c..c08c6cf 100644 --- a/test/Cnblogs.Architecture.UnitTests/Cqrs/Behaviors/CacheBehaviorTests.cs +++ b/test/Cnblogs.Architecture.UnitTests/Cqrs/Behaviors/CacheBehaviorTests.cs @@ -9,8 +9,8 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; - -using Moq; +using NSubstitute; +using NSubstitute.ExceptionExtensions; namespace Cnblogs.Architecture.UnitTests.Cqrs.Behaviors; @@ -20,9 +20,11 @@ public class CacheBehaviorTests public async Task CacheBehavior_DisableCache_NotCacheAsync() { // Arrange - var local = new Mock(); + var local = Substitute.For(); local.AddCacheValue("cacheKey", "cacheValue"); - var behavior = GetBehavior, string>(new List { local.Object }); + var remote = Substitute.For(); + remote.AddCacheValue("cacheKey", "cacheValue"); + var behavior = GetBehavior, string>(new List { local, remote }); // Act var result = await behavior.Handle( @@ -42,8 +44,8 @@ public async Task CacheBehavior_DisableCache_NotCacheAsync() public async Task CacheBehavior_EnableLocal_NoCache_UpdateAsync() { // Arrange - var local = new Mock(); - var behavior = GetBehavior, string>(new List { local.Object }); + var local = Substitute.For(); + var behavior = GetBehavior, string>(new List { local }); // Act var result = await behavior.Handle( @@ -58,17 +60,17 @@ public async Task CacheBehavior_EnableLocal_NoCache_UpdateAsync() // Assert result.Should().Be("noCache"); - local.Verify(x => x.UpdateAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + await local.Received(1).UpdateAsync(Arg.Any(), Arg.Any(), Arg.Any()); } [Fact] public async Task CacheBehavior_EnableLocal_HasCache_UseCacheAsync() { // Arrange - var local = new Mock(); + var local = Substitute.For(); local.AddCacheValue("cacheKey", "cacheValue"); - var remote = new Mock(); - var behavior = GetBehavior, string>(new List { local.Object, remote.Object }); + var remote = Substitute.For(); + var behavior = GetBehavior, string>(new List { local, remote }); // Act var result = await behavior.Handle( @@ -83,17 +85,17 @@ public async Task CacheBehavior_EnableLocal_HasCache_UseCacheAsync() // Assert result.Should().Be("cacheValue"); - local.Verify(x => x.UpdateAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); - remote.Verify(x => x.GetAsync(It.IsAny()), Times.Never); + await local.Received(0).UpdateAsync(Arg.Any(), Arg.Any(), Arg.Any()); + await remote.Received(0).GetAsync(Arg.Any()); } [Fact] public async Task CacheBehavior_EnableRemote_NoCache_UpdateAsync() { // Arrange - var remote = new Mock(); - var local = new Mock(); - var behavior = GetBehavior, string>(new List { local.Object, remote.Object }); + var remote = Substitute.For(); + var local = Substitute.For(); + var behavior = GetBehavior, string>(new List { local, remote }); // Act var result = await behavior.Handle( @@ -108,17 +110,17 @@ public async Task CacheBehavior_EnableRemote_NoCache_UpdateAsync() // Assert result.Should().Be("noCache"); - local.Verify(x => x.UpdateAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); - remote.Verify(x => x.UpdateAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + await local.Received(0).UpdateAsync(Arg.Any(), Arg.Any(), Arg.Any()); + await remote.Received(1).UpdateAsync(Arg.Any(), Arg.Any(), Arg.Any()); } [Fact] public async Task CacheBehavior_EnableRemote_HasCache_UseCacheAsync() { // Arrange - var remote = new Mock().AddCacheValue("cacheKey", "cacheValue"); - var local = new Mock(); - var behavior = GetBehavior, string>(new List { local.Object, remote.Object }); + var remote = Substitute.For().AddCacheValue("cacheKey", "cacheValue"); + var local = Substitute.For(); + var behavior = GetBehavior, string>(new List { local, remote }); // Act var result = await behavior.Handle( @@ -133,17 +135,17 @@ public async Task CacheBehavior_EnableRemote_HasCache_UseCacheAsync() // Assert result.Should().Be("cacheValue"); - local.Verify(x => x.GetAsync(It.IsAny()), Times.Never); + await local.Received(0).GetAsync(Arg.Any()); } [Fact] public async Task CacheBehavior_ThrowOnGet_ThrowAsync() { // Arrange - var remote = new Mock(); - remote.Setup(x => x.GetAsync(It.IsAny())).ThrowsAsync(new Exception("test")); + var remote = Substitute.For(); + remote.GetAsync(Arg.Any()).ThrowsAsync(new Exception("test")); var behavior = GetBehavior, string>( - new List() { remote.Object }, + new List() { remote }, o => o.ThrowIfFailedOnGet = true); // Act @@ -165,10 +167,10 @@ public async Task CacheBehavior_ThrowOnGet_ThrowAsync() public async Task CacheBehavior_ThrowOnGet_NoThrowAsync() { // Arrange - var remote = new Mock(); - remote.Setup(x => x.GetAsync(It.IsAny())).ThrowsAsync(new Exception("test")); + var remote = Substitute.For(); + remote.GetAsync(Arg.Any()).ThrowsAsync(new Exception("test")); var behavior = GetBehavior, string>( - new List() { remote.Object }, + new List() { remote }, o => o.ThrowIfFailedOnGet = false); // Act @@ -190,11 +192,11 @@ public async Task CacheBehavior_ThrowOnGet_NoThrowAsync() public async Task CacheBehavior_ThrowOnUpdate_ThrowAsync() { // Arrange - var remote = new Mock(); - remote.Setup(x => x.UpdateAsync(It.IsAny(), It.IsAny(), It.IsAny())) + var remote = Substitute.For(); + remote.UpdateAsync(Arg.Any(), Arg.Any(), Arg.Any()) .ThrowsAsync(new Exception("test")); var behavior = GetBehavior, string>( - new List { remote.Object }, + new List { remote }, o => o.ThrowIfFailedOnUpdate = true); // Act @@ -216,11 +218,11 @@ public async Task CacheBehavior_ThrowOnUpdate_ThrowAsync() public async Task CacheBehavior_NotThrowOnUpdate_NotThrowAsync() { // Arrange - var remote = new Mock(); - remote.Setup(x => x.UpdateAsync(It.IsAny(), It.IsAny(), It.IsAny())) + var remote = Substitute.For(); + remote.UpdateAsync(Arg.Any(), Arg.Any(), Arg.Any()) .ThrowsAsync(new Exception("test")); var behavior = GetBehavior, string>( - new List { remote.Object }, + new List { remote }, o => o.ThrowIfFailedOnUpdate = false); // Act @@ -262,4 +264,4 @@ private static CacheableRequestBehavior GetBehavior(option), NullLogger>.Instance); } -} \ No newline at end of file +} diff --git a/test/Cnblogs.Architecture.UnitTests/Cqrs/Behaviors/LoggerBehaviorTests.cs b/test/Cnblogs.Architecture.UnitTests/Cqrs/Behaviors/LoggerBehaviorTests.cs index 0998fd5..292254c 100644 --- a/test/Cnblogs.Architecture.UnitTests/Cqrs/Behaviors/LoggerBehaviorTests.cs +++ b/test/Cnblogs.Architecture.UnitTests/Cqrs/Behaviors/LoggerBehaviorTests.cs @@ -1,9 +1,7 @@ using Cnblogs.Architecture.Ddd.Cqrs.Abstractions; using Cnblogs.Architecture.UnitTests.Cqrs.FakeObjects; - using Microsoft.Extensions.Logging; - -using Moq; +using NSubstitute; namespace Cnblogs.Architecture.UnitTests.Cqrs.Behaviors; @@ -13,21 +11,56 @@ public class LoggerBehaviorTests public async Task LoggerBehavior_ShouldLogDebugAsync() { // Arrange - var logger = new Mock, string>>>(); - var behavior = new LoggingBehavior, string>(logger.Object); + var logger = Substitute.For, string>>>(); + var behavior = + new LoggingBehavior, string>( + new TestLogger, string>>(logger)); var request = new FakeQuery(null, "test"); // Act await behavior.Handle(request, () => Task.FromResult("done"), default); // Assert - logger.Verify( - x => x.Log( - LogLevel.Debug, - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>()), - Times.Exactly(2)); + logger.Received(2).Log( + LogLevel.Debug, + Arg.Any(), + Arg.Any(), + null, + Arg.Any>()); + } + + private class TestLogger : ILogger + { + private readonly ILogger _logger; + + // ReSharper disable once ContextualLoggerProblem + public TestLogger(ILogger logger) + { + _logger = logger; + } + + /// + public IDisposable? BeginScope(TState state) + where TState : notnull + { + return _logger.BeginScope(state); + } + + /// + public virtual bool IsEnabled(LogLevel logLevel) + { + return _logger.IsEnabled(logLevel); + } + + /// + public virtual void Log( + LogLevel logLevel, + EventId eventId, + TState state, + Exception? exception, + Func formatter) + { + _logger.Log(logLevel, eventId, state!, exception, (_, _) => string.Empty); + } } -} \ No newline at end of file +} diff --git a/test/Cnblogs.Architecture.UnitTests/Cqrs/FakeObjects/CacheMockExtensions.cs b/test/Cnblogs.Architecture.UnitTests/Cqrs/FakeObjects/CacheMockExtensions.cs index b991114..740fd7e 100644 --- a/test/Cnblogs.Architecture.UnitTests/Cqrs/FakeObjects/CacheMockExtensions.cs +++ b/test/Cnblogs.Architecture.UnitTests/Cqrs/FakeObjects/CacheMockExtensions.cs @@ -1,26 +1,21 @@ using Cnblogs.Architecture.Ddd.Infrastructure.Abstractions; - -using Moq; +using NSubstitute; namespace Cnblogs.Architecture.UnitTests.Cqrs.FakeObjects; public static class CacheMockExtensions { - public static Mock AddCacheValue(this Mock mock, string key, T value) + public static ICacheProvider AddCacheValue(this ILocalCacheProvider mock, string key, T value) { - mock.As() - .Setup(x => x.GetAsync(key.ToLower())) - .ReturnsAsync(new CacheEntry(value, DateTimeOffset.Now.ToUnixTimeSeconds())); - mock.As() - .Setup(x => x.GetAsync(key.ToLower())) - .ReturnsAsync(new CacheEntry(value, DateTimeOffset.Now.ToUnixTimeSeconds())); + mock.GetAsync(key.ToLower()) + .Returns(new CacheEntry(value, DateTimeOffset.Now.ToUnixTimeSeconds())); return mock; } - public static Mock AddCacheValue(this Mock mock, string key, T value) + public static IRemoteCacheProvider AddCacheValue(this IRemoteCacheProvider mock, string key, T value) { - mock.Setup(x => x.GetAsync(key.ToLower())) - .ReturnsAsync(new CacheEntry(value, DateTimeOffset.Now.ToUnixTimeSeconds())); + mock.GetAsync(key.ToLower()) + .Returns(new CacheEntry(value, DateTimeOffset.Now.ToUnixTimeSeconds())); return mock; } -} \ No newline at end of file +} diff --git a/test/Cnblogs.Architecture.UnitTests/Cqrs/Handlers/InvalidCacheRequestHandlerTests.cs b/test/Cnblogs.Architecture.UnitTests/Cqrs/Handlers/InvalidCacheRequestHandlerTests.cs index 15045d5..9461e6c 100644 --- a/test/Cnblogs.Architecture.UnitTests/Cqrs/Handlers/InvalidCacheRequestHandlerTests.cs +++ b/test/Cnblogs.Architecture.UnitTests/Cqrs/Handlers/InvalidCacheRequestHandlerTests.cs @@ -7,8 +7,8 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; - -using Moq; +using NSubstitute; +using NSubstitute.ExceptionExtensions; namespace Cnblogs.Architecture.UnitTests.Cqrs.Handlers; @@ -18,11 +18,11 @@ public class InvalidCacheRequestHandlerTests public Task InvalidCache_ThrowOnRemove_ThrowAsync() { // Arrange - var provider = new Mock(); - provider.Setup(x => x.RemoveAsync(It.IsAny())) + var provider = Substitute.For(); + provider.RemoveAsync(Arg.Any()) .ThrowsAsync(new InvalidOperationException()); var handler = CreateInvalidCacheRequestHandler( - new List() { provider.Object }, + new List() { provider }, o => o.ThrowIfFailedOnRemove = true); // Act @@ -31,18 +31,18 @@ public Task InvalidCache_ThrowOnRemove_ThrowAsync() CancellationToken.None); // Assert - return Assert.ThrowsAsync(act); + return act.Should().ThrowAsync(); } [Fact] public Task InvalidCache_ThrowOnRemove_NotThrowAsync() { // Arrange - var provider = new Mock(); - provider.Setup(x => x.RemoveAsync(It.IsAny())) + var provider = Substitute.For(); + provider.RemoveAsync(Arg.Any()) .ThrowsAsync(new InvalidOperationException()); var handler = CreateInvalidCacheRequestHandler( - new List() { provider.Object }, + new List() { provider }, o => o.ThrowIfFailedOnRemove = false); // Act @@ -58,11 +58,11 @@ public Task InvalidCache_ThrowOnRemove_NotThrowAsync() public Task InvalidCache_ThrowOnRemove_OverrideByRequest_NotThrowAsync() { // Arrange - var provider = new Mock(); - provider.Setup(x => x.RemoveAsync(It.IsAny())) + var provider = Substitute.For(); + provider.RemoveAsync(Arg.Any()) .ThrowsAsync(new InvalidOperationException()); var handler = CreateInvalidCacheRequestHandler( - new List() { provider.Object }, + new List() { provider }, o => o.ThrowIfFailedOnRemove = true); // Act @@ -78,10 +78,10 @@ public Task InvalidCache_ThrowOnRemove_OverrideByRequest_NotThrowAsync() public async Task InvalidCache_RemoveCacheAsync() { // Arrange - var remote = new Mock(); - var local = new Mock(); + var remote = Substitute.For(); + var local = Substitute.For(); var handler = CreateInvalidCacheRequestHandler( - new List() { remote.Object, local.Object }, + new List() { remote, local }, o => o.ThrowIfFailedOnRemove = false); // Act @@ -90,18 +90,18 @@ await handler.Handle( CancellationToken.None); // Assert - local.Verify(x => x.RemoveAsync(It.IsAny()), Times.Once); - remote.Verify(x => x.RemoveAsync(It.IsAny()), Times.Once); + await local.Received(1).RemoveAsync(Arg.Any()); + await remote.Received(1).RemoveAsync(Arg.Any()); } [Fact] public async Task InvalidCache_RemoveGroupCacheAsync() { // Arrange - var remote = new Mock(); - var local = new Mock(); + var remote = Substitute.For(); + var local = Substitute.For(); var handler = CreateInvalidCacheRequestHandler( - new List() { remote.Object, local.Object }, + new List() { remote, local }, o => o.ThrowIfFailedOnRemove = false); // Act @@ -110,10 +110,10 @@ await handler.Handle( CancellationToken.None); // Assert - local.Verify(x => x.RemoveAsync(It.IsAny()), Times.Once); - local.Verify(x => x.UpdateAsync(It.IsAny(), It.IsAny()), Times.Once); - remote.Verify(x => x.RemoveAsync(It.IsAny()), Times.Once); - remote.Verify(x => x.UpdateAsync(It.IsAny(), It.IsAny()), Times.Once); + await local.Received(1).RemoveAsync(Arg.Any()); + await local.Received(1).UpdateAsync(Arg.Any(), Arg.Any()); + await remote.Received(1).RemoveAsync(Arg.Any()); + await remote.Received(1).UpdateAsync(Arg.Any(), Arg.Any()); } [Fact] @@ -138,4 +138,4 @@ private InvalidCacheRequestHandler CreateInvalidCacheRequestHandler( new OptionsWrapper(option), NullLogger.Instance); } -} \ No newline at end of file +} diff --git a/test/Cnblogs.Architecture.UnitTests/Infrastructure/EntityFramework/BaseRepositoryTests.cs b/test/Cnblogs.Architecture.UnitTests/Infrastructure/EntityFramework/BaseRepositoryTests.cs index f724568..c83035c 100644 --- a/test/Cnblogs.Architecture.UnitTests/Infrastructure/EntityFramework/BaseRepositoryTests.cs +++ b/test/Cnblogs.Architecture.UnitTests/Infrastructure/EntityFramework/BaseRepositoryTests.cs @@ -4,7 +4,8 @@ using FluentAssertions; using MediatR; using Microsoft.EntityFrameworkCore; -using Moq; +using NSubstitute; +using NSubstitute.ExceptionExtensions; namespace Cnblogs.Architecture.UnitTests.Infrastructure.EntityFramework; @@ -26,7 +27,7 @@ public async Task GetEntityAsync_Include_GetEntityAsync() new DbContextOptionsBuilder().UseInMemoryDatabase("inmemory").Options); db.Add(entity); await db.SaveChangesAsync(); - var repository = new TestRepository(Mock.Of(), db); + var repository = new TestRepository(Substitute.For(), db); // Act var got = await repository.GetAsync(entity.Id, e => e.Posts); @@ -52,7 +53,7 @@ public async Task GetEntityAsync_StringBasedInclude_NotNullAsync() new DbContextOptionsBuilder().UseInMemoryDatabase("inmemory").Options); db.Add(entity); await db.SaveChangesAsync(); - var repository = new TestRepository(Mock.Of(), db); + var repository = new TestRepository(Substitute.For(), db); // Act var got = await repository.GetAsync(entity.Id, new List() { nameof(entity.Posts) }); @@ -79,7 +80,7 @@ public async Task GetEntityAsync_ThenInclude_NotNullAsync() new DbContextOptionsBuilder().UseInMemoryDatabase("inmemory").Options); db.Add(entity); await db.SaveChangesAsync(); - var repository = new TestRepository(Mock.Of(), db); + var repository = new TestRepository(Substitute.For(), db); // Act var got = await repository.GetAsync(entity.Id, new List() { "Posts.Tags" }); @@ -105,7 +106,7 @@ public async Task SaveEntitiesAsync_CallBeforeUpdateForRelatedEntity_UpdateDateU new DbContextOptionsBuilder().UseInMemoryDatabase("inmemory").Options); db.Add(entity); await db.SaveChangesAsync(); - var repository = new TestRepository(Mock.Of(), db); + var repository = new TestRepository(Substitute.For(), db); // Act entity.Title = "new title"; @@ -133,8 +134,8 @@ public async Task SaveEntitiesAsync_DispatchEntityDomainEvents_DispatchAllAsync( new DbContextOptionsBuilder().UseInMemoryDatabase("inmemory").Options); db.Add(entity); await db.SaveChangesAsync(); - var mediator = new Mock(); - var repository = new TestRepository(mediator.Object, db); + var mediator = Substitute.For(); + var repository = new TestRepository(mediator, db); // Act entity.Title = "new title"; @@ -143,16 +144,12 @@ public async Task SaveEntitiesAsync_DispatchEntityDomainEvents_DispatchAllAsync( await repository.UpdateAsync(entity); // Assert - mediator.Verify( - x => x.Publish( - It.Is(d => ((FakeDomainEvent)d).FakeValue == 1), - It.IsAny()), - Times.Once); - mediator.Verify( - x => x.Publish( - It.Is(d => ((FakeDomainEvent)d).FakeValue == 2), - It.IsAny()), - Times.Once); + await mediator.Received(1).Publish( + Arg.Is(d => ((FakeDomainEvent)d).FakeValue == 1), + Arg.Any()); + await mediator.Received(1).Publish( + Arg.Is(d => ((FakeDomainEvent)d).FakeValue == 2), + Arg.Any()); } [Fact] @@ -171,8 +168,8 @@ public async Task SaveEntitiesAsync_DispatchRelatedEntityDomainEvents_DispatchAl new DbContextOptionsBuilder().UseInMemoryDatabase("inmemory").Options); db.Add(entity); await db.SaveChangesAsync(); - var mediator = new Mock(); - var repository = new TestRepository(mediator.Object, db); + var mediator = Substitute.For(); + var repository = new TestRepository(mediator, db); // Act entity.Title = "new title"; @@ -182,16 +179,12 @@ public async Task SaveEntitiesAsync_DispatchRelatedEntityDomainEvents_DispatchAl await repository.UpdateAsync(entity); // Assert - mediator.Verify( - x => x.Publish( - It.Is(d => ((FakeDomainEvent)d).FakeValue == 1), - It.IsAny()), - Times.Once); - mediator.Verify( - x => x.Publish( - It.Is(d => ((FakeDomainEvent)d).FakeValue == 2), - It.IsAny()), - Times.Once); + await mediator.Received(1).Publish( + Arg.Is(d => ((FakeDomainEvent)d).FakeValue == 1), + Arg.Any()); + await mediator.Received(1).Publish( + Arg.Is(d => ((FakeDomainEvent)d).FakeValue == 2), + Arg.Any()); } [Fact] @@ -208,8 +201,8 @@ public async Task SaveEntitiesAsync_DispatchEntityDomainEventsWithGeneratedId_Di .GenerateSingle(); var db = new FakeDbContext( new DbContextOptionsBuilder().UseInMemoryDatabase("inmemory").Options); - var mediator = new Mock(); - var repository = new TestRepository(mediator.Object, db); + var mediator = Substitute.For(); + var repository = new TestRepository(mediator, db); // Act entity.AddDomainEvent(id => new FakeDomainEvent(id, 1)); @@ -217,16 +210,12 @@ public async Task SaveEntitiesAsync_DispatchEntityDomainEventsWithGeneratedId_Di await repository.AddAsync(entity); // Assert - mediator.Verify( - x => x.Publish( - It.Is(d => ((FakeDomainEvent)d).Id != 0 && ((FakeDomainEvent)d).FakeValue == 1), - It.IsAny()), - Times.Once); - mediator.Verify( - x => x.Publish( - It.Is(d => ((FakeDomainEvent)d).Id != 0 && ((FakeDomainEvent)d).FakeValue == 2), - It.IsAny()), - Times.Exactly(entity.Posts.Count)); + await mediator.Received(1).Publish( + Arg.Is(d => ((FakeDomainEvent)d).Id != 0 && ((FakeDomainEvent)d).FakeValue == 1), + Arg.Any()); + await mediator.Received(entity.Posts.Count).Publish( + Arg.Is(d => ((FakeDomainEvent)d).Id != 0 && ((FakeDomainEvent)d).FakeValue == 2), + Arg.Any()); } [Fact] @@ -243,10 +232,10 @@ public async Task SaveEntitiesAsync_DispatchEntityDomainEventsWithMultipleExcept .GenerateSingle(); var db = new FakeDbContext( new DbContextOptionsBuilder().UseInMemoryDatabase("inmemory").Options); - var mediator = new Mock(); - mediator.Setup(x => x.Publish(It.IsAny(), It.IsAny())) + var mediator = Substitute.For(); + mediator.Publish(Arg.Any(), Arg.Any()) .Throws(); - var repository = new TestRepository(mediator.Object, db); + var repository = new TestRepository(mediator, db); // Act entity.AddDomainEvent(id => new FakeDomainEvent(id, 1)); @@ -257,15 +246,11 @@ public async Task SaveEntitiesAsync_DispatchEntityDomainEventsWithMultipleExcept var eventCount = 1 + entity.Posts.Count; (await act.Should().ThrowAsync()).And.InnerExceptions.Should() .HaveCount(eventCount); - mediator.Verify( - x => x.Publish( - It.Is(d => ((FakeDomainEvent)d).Id != 0 && ((FakeDomainEvent)d).FakeValue == 1), - It.IsAny()), - Times.Once); - mediator.Verify( - x => x.Publish( - It.Is(d => ((FakeDomainEvent)d).Id != 0 && ((FakeDomainEvent)d).FakeValue == 2), - It.IsAny()), - Times.Exactly(entity.Posts.Count)); + await mediator.Received(1).Publish( + Arg.Is(d => ((FakeDomainEvent)d).Id != 0 && ((FakeDomainEvent)d).FakeValue == 1), + Arg.Any()); + await mediator.Received(entity.Posts.Count).Publish( + Arg.Is(d => ((FakeDomainEvent)d).Id != 0 && ((FakeDomainEvent)d).FakeValue == 2), + Arg.Any()); } } diff --git a/test/Cnblogs.Architecture.UnitTests/Infrastructure/FakeObjects/FakeMongoDbContext.cs b/test/Cnblogs.Architecture.UnitTests/Infrastructure/FakeObjects/FakeMongoDbContext.cs index 31e797c..6210ca0 100644 --- a/test/Cnblogs.Architecture.UnitTests/Infrastructure/FakeObjects/FakeMongoDbContext.cs +++ b/test/Cnblogs.Architecture.UnitTests/Infrastructure/FakeObjects/FakeMongoDbContext.cs @@ -1,40 +1,38 @@ using Cnblogs.Architecture.Ddd.Infrastructure.MongoDb; using MongoDB.Driver; -using Moq; +using NSubstitute; namespace Cnblogs.Architecture.UnitTests.Infrastructure.FakeObjects; public class FakeMongoDbContext : MongoContext { - public Mock MongoDatabaseMock { get; } - public Mock MongoClientMock { get; } - public Mock ClientSessionHandleMock { get; } - public Mock OptionsMock { get; } + public IMongoDatabase MongoDatabaseMock { get; } + public IMongoClient MongoClientMock { get; } + public IClientSessionHandle ClientSessionHandleMock { get; } + public IMongoContextOptions OptionsMock { get; } public FakeMongoDbContext() : this(MockOptions()) { } - public FakeMongoDbContext(Mock mockOptionsMock) + public FakeMongoDbContext(IMongoContextOptions mockOptionsMock) : this(mockOptionsMock, MockDatabase(mockOptionsMock)) { } - public FakeMongoDbContext(Mock mockOptionsMock, Mock mongoDatabase) - : base(mockOptionsMock.Object) + public FakeMongoDbContext(IMongoContextOptions mockOptionsMock, IMongoDatabase mongoDatabase) + : base(mockOptionsMock) { OptionsMock = mockOptionsMock; MongoDatabaseMock = mongoDatabase; - ClientSessionHandleMock = new Mock(); - MongoClientMock = new Mock(); - MongoClientMock - .Setup(x => x.StartSessionAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(ClientSessionHandleMock.Object); - MongoDatabaseMock.Setup(x => x.Client).Returns(MongoClientMock.Object); - MongoDatabaseMock - .Setup(x => x.GetCollection(It.IsAny(), null)) - .Returns(Mock.Of>()); + ClientSessionHandleMock = Substitute.For(); + MongoClientMock = Substitute.For(); + MongoClientMock.StartSessionAsync(Arg.Any(), Arg.Any()) + .Returns(ClientSessionHandleMock); + MongoDatabaseMock.Client.Returns(MongoClientMock); + MongoDatabaseMock.GetCollection(Arg.Any()) + .Returns(Substitute.For>()); } /// @@ -45,15 +43,15 @@ protected override void ConfigureModels(MongoModelBuilder builder) builder.Entity("fakeTag"); } - private static Mock MockOptions() + private static IMongoContextOptions MockOptions() { - return new Mock(); + return Substitute.For(); } - private static Mock MockDatabase(Mock mongoContextOptionsMock) + private static IMongoDatabase MockDatabase(IMongoContextOptions mongoContextOptionsMock) { - var mock = new Mock(); - mongoContextOptionsMock.Setup(x => x.GetDatabase()).Returns(mock.Object); + var mock = Substitute.For(); + mongoContextOptionsMock.GetDatabase().Returns(mock); return mock; } } diff --git a/test/Cnblogs.Architecture.UnitTests/Infrastructure/FakeObjects/TestMongoRepository.cs b/test/Cnblogs.Architecture.UnitTests/Infrastructure/FakeObjects/TestMongoRepository.cs index ae68908..4a426aa 100644 --- a/test/Cnblogs.Architecture.UnitTests/Infrastructure/FakeObjects/TestMongoRepository.cs +++ b/test/Cnblogs.Architecture.UnitTests/Infrastructure/FakeObjects/TestMongoRepository.cs @@ -1,23 +1,23 @@ using Cnblogs.Architecture.Ddd.Infrastructure.MongoDb; using MediatR; -using Moq; +using NSubstitute; namespace Cnblogs.Architecture.UnitTests.Infrastructure.FakeObjects; public class TestMongoRepository : MongoBaseRepository { - public Mock MediatorMock { get; } + public IMediator MediatorMock { get; } public FakeMongoDbContext MongoDbContext { get; } public TestMongoRepository() - : this(new FakeMongoDbContext(), new Mock()) + : this(new FakeMongoDbContext(), Substitute.For()) { } - public TestMongoRepository(FakeMongoDbContext fakeDbContext, Mock mediator) - : base(fakeDbContext, mediator.Object) + public TestMongoRepository(FakeMongoDbContext fakeDbContext, IMediator mediator) + : base(fakeDbContext, mediator) { MongoDbContext = fakeDbContext; MediatorMock = mediator; } -} \ No newline at end of file +} diff --git a/test/Cnblogs.Architecture.UnitTests/Infrastructure/MongoDb/MongoBaseRepositoryTests.cs b/test/Cnblogs.Architecture.UnitTests/Infrastructure/MongoDb/MongoBaseRepositoryTests.cs index 97515fb..736370c 100644 --- a/test/Cnblogs.Architecture.UnitTests/Infrastructure/MongoDb/MongoBaseRepositoryTests.cs +++ b/test/Cnblogs.Architecture.UnitTests/Infrastructure/MongoDb/MongoBaseRepositoryTests.cs @@ -2,7 +2,7 @@ using Cnblogs.Architecture.UnitTests.Infrastructure.FakeObjects; using FluentAssertions; using MongoDB.Driver; -using Moq; +using NSubstitute; namespace Cnblogs.Architecture.UnitTests.Infrastructure.MongoDb; @@ -21,12 +21,13 @@ public async Task AddAsync_WithDomainEvent_SaveThenPublishAsync() // Assert response.Should().NotBeNull(); - Mock.Get(repository.MongoDbContext.MongoDatabaseMock.Object.GetCollection(string.Empty)).Verify( - x => x.InsertOneAsync(It.IsAny(), It.IsAny(), It.IsAny()), - Times.Once); - repository.MediatorMock.Verify( - x => x.Publish(It.IsAny(), It.IsAny()), - Times.Once); + await repository.MongoDbContext.MongoDatabaseMock.GetCollection(string.Empty) + .Received(1) + .InsertOneAsync( + Arg.Any(), + Arg.Any(), + Arg.Any()); + await repository.MediatorMock.Received(1).Publish(Arg.Any(), Arg.Any()); } [Fact] @@ -42,16 +43,14 @@ public async Task AddRangeAsync_WithDomainEvent_SaveThenPublishAsync() // Assert response.Should().HaveSameCount(blogs); - Mock.Get(repository.MongoDbContext.MongoDatabaseMock.Object.GetCollection(string.Empty)) - .Verify( - x => x.InsertManyAsync( - It.IsAny>(), - It.IsAny(), - It.IsAny()), - Times.Once); - repository.MediatorMock.Verify( - x => x.Publish(It.IsAny(), It.IsAny()), - Times.Exactly(blogs.Count)); + await repository.MongoDbContext.MongoDatabaseMock.GetCollection(string.Empty) + .Received(1) + .InsertManyAsync( + Arg.Any>(), + Arg.Any(), + Arg.Any()); + await repository.MediatorMock.Received(blogs.Count) + .Publish(Arg.Any(), Arg.Any()); } [Fact] @@ -67,11 +66,10 @@ public async Task DeleteAsync_WithDomainEvent_SaveThenPublishAsync() // Assert response.Should().NotBeNull(); - Mock.Get(repository.MongoDbContext.MongoDatabaseMock.Object.GetCollection(string.Empty)) - .Verify( - x => x.DeleteOneAsync(It.IsAny>(), It.IsAny()), - Times.Once); - repository.MediatorMock.Verify(x => x.Publish(It.IsAny(), It.IsAny())); + await repository.MongoDbContext.MongoDatabaseMock.GetCollection(string.Empty) + .Received(1) + .DeleteOneAsync(Arg.Any>(), Arg.Any()); + await repository.MediatorMock.Received().Publish(Arg.Any(), Arg.Any()); } [Fact] @@ -87,15 +85,14 @@ public async Task UpdateAsync_WithDomainEvent_SaveThenPublishAsync() // Assert response.Should().NotBeNull(); - Mock.Get(repository.MongoDbContext.MongoDatabaseMock.Object.GetCollection(string.Empty)) - .Verify( - x => x.ReplaceOneAsync( - It.IsAny>(), - It.IsAny(), - It.IsAny(), - It.IsAny()), - Times.Once); - repository.MediatorMock.Verify(x => x.Publish(It.IsAny(), It.IsAny())); + await repository.MongoDbContext.MongoDatabaseMock.GetCollection(string.Empty) + .Received(1) + .ReplaceOneAsync( + Arg.Any>(), + Arg.Any(), + Arg.Any(), + Arg.Any()); + await repository.MediatorMock.Received().Publish(Arg.Any(), Arg.Any()); } [Fact] @@ -111,16 +108,13 @@ public async Task UpdateRangeAsync_WithDomainEvent_SaveThenPublishAsync() // Assert response.Should().HaveSameCount(blogs); - Mock.Get(repository.MongoDbContext.MongoDatabaseMock.Object.GetCollection(string.Empty)) - .Verify( - x => x.BulkWriteAsync( - It.IsAny>>(), - It.IsAny(), - It.IsAny()), - Times.Once); - repository.MediatorMock.Verify( - x => x.Publish(It.IsAny(), It.IsAny()), - Times.Exactly(blogs.Count)); + await repository.MongoDbContext.MongoDatabaseMock.GetCollection(string.Empty).Received(1) + .BulkWriteAsync( + Arg.Any>>(), + Arg.Any(), + Arg.Any()); + await repository.MediatorMock.Received(blogs.Count) + .Publish(Arg.Any(), Arg.Any()); } [Fact] @@ -138,20 +132,15 @@ public async Task Uow_Insert_CommitAsync() // Assert response.Should().BeTrue(); - repository.MongoDbContext.ClientSessionHandleMock.Verify( - x => x.CommitTransactionAsync(It.IsAny()), - Times.Once); - Mock.Get(repository.MongoDbContext.MongoDatabaseMock.Object.GetCollection(string.Empty)) - .Verify( - x => x.BulkWriteAsync( - It.IsAny(), - It.IsAny>>(), - It.IsAny(), - It.IsAny()), - Times.Once); - repository.MediatorMock.Verify( - x => x.Publish(It.IsAny(), It.IsAny()), - Times.Once); + await repository.MongoDbContext.ClientSessionHandleMock.Received(1) + .CommitTransactionAsync(Arg.Any()); + await repository.MongoDbContext.MongoDatabaseMock.GetCollection(string.Empty).Received(1) + .BulkWriteAsync( + Arg.Any(), + Arg.Any>>(), + Arg.Any(), + Arg.Any()); + await repository.MediatorMock.Received(1).Publish(Arg.Any(), Arg.Any()); } [Fact] @@ -170,17 +159,13 @@ public async Task Uow_InsertThenRemove_NoChangeAsync() // Assert response.Should().BeTrue(); - Mock.Get(repository.MongoDbContext.MongoDatabaseMock.Object.GetCollection(string.Empty)) - .Verify( - x => x.BulkWriteAsync( - It.IsAny(), - It.IsAny>>(), - It.IsAny(), - It.IsAny()), - Times.Never); - repository.MediatorMock.Verify( - x => x.Publish(It.IsAny(), It.IsAny()), - Times.Never); + await repository.MongoDbContext.MongoDatabaseMock.GetCollection(string.Empty).Received(0) + .BulkWriteAsync( + Arg.Any(), + Arg.Any>>(), + Arg.Any(), + Arg.Any()); + await repository.MediatorMock.Received(0).Publish(Arg.Any(), Arg.Any()); } [Fact] @@ -199,17 +184,13 @@ public async Task Uow_DeleteThenInsert_UpdateAsync() // Assert response.Should().BeTrue(); - Mock.Get(repository.MongoDbContext.MongoDatabaseMock.Object.GetCollection(string.Empty)) - .Verify( - x => x.BulkWriteAsync( - It.IsAny(), - It.Is>>(y => y.Any(z => z is ReplaceOneModel)), - It.IsAny(), - It.IsAny()), - Times.Once); - repository.MediatorMock.Verify( - x => x.Publish(It.IsAny(), It.IsAny()), - Times.Once); + await repository.MongoDbContext.MongoDatabaseMock.GetCollection(string.Empty).Received(1) + .BulkWriteAsync( + Arg.Any(), + Arg.Is>>(y => y.Any(z => z is ReplaceOneModel)), + Arg.Any(), + Arg.Any()); + await repository.MediatorMock.Received(1).Publish(Arg.Any(), Arg.Any()); } [Fact] @@ -261,19 +242,14 @@ public async Task Uow_DeleteWithDomainEvent_CommitAsync() // Assert response.Should().BeTrue(); - repository.MongoDbContext.ClientSessionHandleMock.Verify( - x => x.CommitTransactionAsync(It.IsAny()), - Times.Once); - Mock.Get(repository.MongoDbContext.MongoDatabaseMock.Object.GetCollection(string.Empty)) - .Verify( - x => x.BulkWriteAsync( - It.IsAny(), - It.IsAny>>(), - It.IsAny(), - It.IsAny()), - Times.Once); - repository.MediatorMock.Verify( - x => x.Publish(It.IsAny(), It.IsAny()), - Times.Once); + await repository.MongoDbContext.ClientSessionHandleMock.Received(1) + .CommitTransactionAsync(Arg.Any()); + await repository.MongoDbContext.MongoDatabaseMock.GetCollection(string.Empty).Received(1) + .BulkWriteAsync( + Arg.Any(), + Arg.Any>>(), + Arg.Any(), + Arg.Any()); + await repository.MediatorMock.Received(1).Publish(Arg.Any(), Arg.Any()); } -} \ No newline at end of file +} diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 49d1e35..4b36e87 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -1,7 +1,14 @@ - + - - false - - \ No newline at end of file + + false + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + From d45e64c50493c051cad1677832ae282df04d499d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 13 Aug 2023 14:49:52 +0800 Subject: [PATCH 2/2] fix: code clean up --- .../Infrastructure/EntityFramework/BaseRepositoryTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Cnblogs.Architecture.UnitTests/Infrastructure/EntityFramework/BaseRepositoryTests.cs b/test/Cnblogs.Architecture.UnitTests/Infrastructure/EntityFramework/BaseRepositoryTests.cs index c83035c..f88c77c 100644 --- a/test/Cnblogs.Architecture.UnitTests/Infrastructure/EntityFramework/BaseRepositoryTests.cs +++ b/test/Cnblogs.Architecture.UnitTests/Infrastructure/EntityFramework/BaseRepositoryTests.cs @@ -234,7 +234,7 @@ public async Task SaveEntitiesAsync_DispatchEntityDomainEventsWithMultipleExcept new DbContextOptionsBuilder().UseInMemoryDatabase("inmemory").Options); var mediator = Substitute.For(); mediator.Publish(Arg.Any(), Arg.Any()) - .Throws(); + .ThrowsAsync(); var repository = new TestRepository(mediator, db); // Act