0
0
mirror of https://github.com/alex289/CleanArchitecture.git synced 2025-06-30 02:31:08 +00:00

test: Replace Moq with NSubstitute

This commit is contained in:
Alexander Konietzko 2023-08-09 19:20:44 +02:00
parent eb197ebc71
commit ca0489c3a1
No known key found for this signature in database
GPG Key ID: BA6905F37AEC2B5B
23 changed files with 175 additions and 206 deletions

View File

@ -9,15 +9,15 @@
<ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.ApplicationStatus" Version="7.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="7.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.9" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.9">
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="7.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.10" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.10">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="7.0.9" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="7.0.10" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="7.0.10" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
</ItemGroup>

View File

@ -9,9 +9,9 @@
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.11.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
<PackageReference Include="MockQueryable.Moq" Version="7.0.0" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.0" />
<PackageReference Include="MockQueryable.NSubstitute" Version="7.0.0" />
<PackageReference Include="NSubstitute" Version="5.0.0" />
<PackageReference Include="xunit" Version="2.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@ -1,32 +1,26 @@
using CleanArchitecture.Domain.Interfaces;
using CleanArchitecture.Domain.Notifications;
using Moq;
using NSubstitute;
namespace CleanArchitecture.Application.Tests.Fixtures.Queries;
public class QueryHandlerBaseFixture
{
public Mock<IMediatorHandler> Bus { get; } = new();
public IMediatorHandler Bus { get; } = Substitute.For<IMediatorHandler>();
public QueryHandlerBaseFixture VerifyExistingNotification(string key, string errorCode, string message)
{
Bus.Verify(
bus => bus.RaiseEventAsync(
It.Is<DomainNotification>(
notification =>
Bus.Received(1).RaiseEventAsync(Arg.Is<DomainNotification>(notification =>
notification.Key == key &&
notification.Code == errorCode &&
notification.Value == message)),
Times.Once);
notification.Value == message));
return this;
}
public QueryHandlerBaseFixture VerifyNoDomainNotification()
{
Bus.Verify(
bus => bus.RaiseEventAsync(It.IsAny<DomainNotification>()),
Times.Never);
Bus.DidNotReceive().RaiseEventAsync(Arg.Any<DomainNotification>());
return this;
}

View File

@ -1,11 +1,10 @@
using System;
using System.Linq;
using CleanArchitecture.Application.Queries.Users.GetAll;
using CleanArchitecture.Domain.Entities;
using CleanArchitecture.Domain.Enums;
using CleanArchitecture.Domain.Interfaces.Repositories;
using MockQueryable.Moq;
using Moq;
using MockQueryable.NSubstitute;
using NSubstitute;
namespace CleanArchitecture.Application.Tests.Fixtures.Queries.Users;
@ -13,50 +12,44 @@ public sealed class GetAllUsersTestFixture : QueryHandlerBaseFixture
{
public GetAllUsersTestFixture()
{
UserRepository = new Mock<IUserRepository>();
UserRepository = Substitute.For<IUserRepository>();
Handler = new GetAllUsersQueryHandler(UserRepository.Object);
Handler = new GetAllUsersQueryHandler(UserRepository);
}
private Mock<IUserRepository> UserRepository { get; }
private IUserRepository UserRepository { get; }
public GetAllUsersQueryHandler Handler { get; }
public Guid ExistingUserId { get; } = Guid.NewGuid();
public void SetupUserAsync()
{
var user = new Mock<User>(() =>
new User(
var user = new User(
ExistingUserId,
"max@mustermann.com",
"Max",
"Mustermann",
"Password",
UserRole.User));
UserRole.User);
var query = new[] { user.Object }.AsQueryable().BuildMock();
var query = new[] { user }.BuildMock();
UserRepository
.Setup(x => x.GetAllNoTracking())
.Returns(query);
UserRepository.GetAllNoTracking().Returns(query);
}
public void SetupDeletedUserAsync()
{
var user = new Mock<User>(() =>
new User(
var user = new User(
ExistingUserId,
"max@mustermann.com",
"Max",
"Mustermann",
"Password",
UserRole.User));
UserRole.User);
user.Object.Delete();
user.Delete();
var query = new[] { user.Object }.AsQueryable().BuildMock();
var query = new[] { user }.BuildMock();
UserRepository
.Setup(x => x.GetAllNoTracking())
.Returns(query);
UserRepository.GetAllNoTracking().Returns(query);
}
}

View File

@ -4,8 +4,8 @@ using CleanArchitecture.Application.Queries.Users.GetUserById;
using CleanArchitecture.Domain.Entities;
using CleanArchitecture.Domain.Enums;
using CleanArchitecture.Domain.Interfaces.Repositories;
using MockQueryable.Moq;
using Moq;
using MockQueryable.NSubstitute;
using NSubstitute;
namespace CleanArchitecture.Application.Tests.Fixtures.Queries.Users;
@ -13,50 +13,44 @@ public sealed class GetUserByIdTestFixture : QueryHandlerBaseFixture
{
public GetUserByIdTestFixture()
{
UserRepository = new Mock<IUserRepository>();
UserRepository = Substitute.For<IUserRepository>();
Handler = new GetUserByIdQueryHandler(UserRepository.Object, Bus.Object);
Handler = new GetUserByIdQueryHandler(UserRepository, Bus);
}
private Mock<IUserRepository> UserRepository { get; }
private IUserRepository UserRepository { get; }
public GetUserByIdQueryHandler Handler { get; }
public Guid ExistingUserId { get; } = Guid.NewGuid();
public void SetupUserAsync()
{
var user = new Mock<User>(() =>
new User(
var user = new User(
ExistingUserId,
"max@mustermann.com",
"Max",
"Mustermann",
"Password",
UserRole.User));
UserRole.User);
var query = new[] { user.Object }.AsQueryable().BuildMock();
var query = new[] { user }.BuildMock();
UserRepository
.Setup(x => x.GetAllNoTracking())
.Returns(query);
UserRepository.GetAllNoTracking().Returns(query);
}
public void SetupDeletedUserAsync()
{
var user = new Mock<User>(() =>
new User(
var user = new User(
ExistingUserId,
"max@mustermann.com",
"Max",
"Mustermann",
"Password",
UserRole.User));
UserRole.User);
user.Object.Delete();
user.Delete();
var query = new[] { user.Object }.AsQueryable().BuildMock();
var query = new[] { user }.AsQueryable().BuildMock();
UserRepository
.Setup(x => x.GetAllNoTracking())
.Returns(query);
UserRepository.GetAllNoTracking().Returns(query);
}
}

View File

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.10" />
</ItemGroup>
<ItemGroup>

View File

@ -10,8 +10,8 @@
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="FluentAssertions" Version="6.11.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.0" />
<PackageReference Include="NSubstitute" Version="5.0.0" />
<PackageReference Include="xunit" Version="2.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@ -2,7 +2,7 @@
using CleanArchitecture.Domain.Commands.Users.ChangePassword;
using CleanArchitecture.Domain.Enums;
using CleanArchitecture.Domain.Interfaces.Repositories;
using Moq;
using NSubstitute;
using BC = BCrypt.Net.BCrypt;
namespace CleanArchitecture.Domain.Tests.CommandHandler.User.ChangePassword;
@ -11,18 +11,18 @@ public sealed class ChangePasswordCommandTestFixture : CommandHandlerFixtureBase
{
public ChangePasswordCommandTestFixture()
{
UserRepository = new Mock<IUserRepository>();
UserRepository = Substitute.For<IUserRepository>();
CommandHandler = new ChangePasswordCommandHandler(
Bus.Object,
UnitOfWork.Object,
NotificationHandler.Object,
UserRepository.Object,
User.Object);
Bus,
UnitOfWork,
NotificationHandler,
UserRepository,
User);
}
public ChangePasswordCommandHandler CommandHandler { get; }
private Mock<IUserRepository> UserRepository { get; }
private IUserRepository UserRepository { get; }
public Entities.User SetupUser()
{
@ -34,11 +34,11 @@ public sealed class ChangePasswordCommandTestFixture : CommandHandlerFixtureBase
BC.HashPassword("z8]tnayvd5FNLU9:]AQm"),
UserRole.User);
User.Setup(x => x.GetUserId()).Returns(user.Id);
User.GetUserId().Returns(user.Id);
UserRepository
.Setup(x => x.GetByIdAsync(It.Is<Guid>(y => y == user.Id)))
.ReturnsAsync(user);
.GetByIdAsync(Arg.Is<Guid>(y => y == user.Id))
.Returns(user);
return user;
}
@ -46,7 +46,7 @@ public sealed class ChangePasswordCommandTestFixture : CommandHandlerFixtureBase
public Guid SetupMissingUser()
{
var id = Guid.NewGuid();
User.Setup(x => x.GetUserId()).Returns(id);
User.GetUserId().Returns(id);
return id;
}
}

View File

@ -2,7 +2,7 @@ using System;
using CleanArchitecture.Domain.Commands.Users.CreateUser;
using CleanArchitecture.Domain.Enums;
using CleanArchitecture.Domain.Interfaces.Repositories;
using Moq;
using NSubstitute;
namespace CleanArchitecture.Domain.Tests.CommandHandler.User.CreateUser;
@ -10,17 +10,17 @@ public sealed class CreateUserCommandTestFixture : CommandHandlerFixtureBase
{
public CreateUserCommandTestFixture()
{
UserRepository = new Mock<IUserRepository>();
UserRepository = Substitute.For<IUserRepository>();
CommandHandler = new CreateUserCommandHandler(
Bus.Object,
UnitOfWork.Object,
NotificationHandler.Object,
UserRepository.Object);
Bus,
UnitOfWork,
NotificationHandler,
UserRepository);
}
public CreateUserCommandHandler CommandHandler { get; }
private Mock<IUserRepository> UserRepository { get; }
private IUserRepository UserRepository { get; }
public Entities.User SetupUser()
{
@ -33,8 +33,8 @@ public sealed class CreateUserCommandTestFixture : CommandHandlerFixtureBase
UserRole.User);
UserRepository
.Setup(x => x.GetByIdAsync(It.Is<Guid>(y => y == user.Id)))
.ReturnsAsync(user);
.GetByIdAsync(Arg.Is<Guid>(y => y == user.Id))
.Returns(user);
return user;
}

View File

@ -2,7 +2,7 @@ using System;
using CleanArchitecture.Domain.Commands.Users.DeleteUser;
using CleanArchitecture.Domain.Enums;
using CleanArchitecture.Domain.Interfaces.Repositories;
using Moq;
using NSubstitute;
namespace CleanArchitecture.Domain.Tests.CommandHandler.User.DeleteUser;
@ -10,18 +10,18 @@ public sealed class DeleteUserCommandTestFixture : CommandHandlerFixtureBase
{
public DeleteUserCommandTestFixture()
{
UserRepository = new Mock<IUserRepository>();
UserRepository = Substitute.For<IUserRepository>();
CommandHandler = new DeleteUserCommandHandler(
Bus.Object,
UnitOfWork.Object,
NotificationHandler.Object,
UserRepository.Object,
User.Object);
Bus,
UnitOfWork,
NotificationHandler,
UserRepository,
User);
}
public DeleteUserCommandHandler CommandHandler { get; }
private Mock<IUserRepository> UserRepository { get; }
private IUserRepository UserRepository { get; }
public Entities.User SetupUser()
{
@ -34,8 +34,8 @@ public sealed class DeleteUserCommandTestFixture : CommandHandlerFixtureBase
UserRole.User);
UserRepository
.Setup(x => x.GetByIdAsync(It.Is<Guid>(y => y == user.Id)))
.ReturnsAsync(user);
.GetByIdAsync(Arg.Is<Guid>(y => y == user.Id))
.Returns(user);
return user;
}

View File

@ -4,7 +4,7 @@ using CleanArchitecture.Domain.Enums;
using CleanArchitecture.Domain.Interfaces.Repositories;
using CleanArchitecture.Domain.Settings;
using Microsoft.Extensions.Options;
using Moq;
using NSubstitute;
using BC = BCrypt.Net.BCrypt;
namespace CleanArchitecture.Domain.Tests.CommandHandler.User.LoginUser;
@ -13,7 +13,7 @@ public sealed class LoginUserCommandTestFixture : CommandHandlerFixtureBase
{
public LoginUserCommandTestFixture()
{
UserRepository = new Mock<IUserRepository>();
UserRepository = Substitute.For<IUserRepository>();
TokenSettings = Options.Create(new TokenSettings
{
@ -23,15 +23,15 @@ public sealed class LoginUserCommandTestFixture : CommandHandlerFixtureBase
});
CommandHandler = new LoginUserCommandHandler(
Bus.Object,
UnitOfWork.Object,
NotificationHandler.Object,
UserRepository.Object,
Bus,
UnitOfWork,
NotificationHandler,
UserRepository,
TokenSettings);
}
public LoginUserCommandHandler CommandHandler { get; set; }
public Mock<IUserRepository> UserRepository { get; set; }
public IUserRepository UserRepository { get; set; }
public IOptions<TokenSettings> TokenSettings { get; set; }
public Entities.User SetupUser()
@ -44,11 +44,11 @@ public sealed class LoginUserCommandTestFixture : CommandHandlerFixtureBase
BC.HashPassword("z8]tnayvd5FNLU9:]AQm"),
UserRole.User);
User.Setup(x => x.GetUserId()).Returns(user.Id);
User.GetUserId().Returns(user.Id);
UserRepository
.Setup(x => x.GetByEmailAsync(It.Is<string>(y => y == user.Email)))
.ReturnsAsync(user);
.GetByEmailAsync(Arg.Is<string>(y => y == user.Email))
.Returns(user);
return user;
}

View File

@ -4,7 +4,7 @@ using CleanArchitecture.Domain.Commands.Users.UpdateUser;
using CleanArchitecture.Domain.Enums;
using CleanArchitecture.Domain.Errors;
using CleanArchitecture.Domain.Events.User;
using Moq;
using NSubstitute;
using Xunit;
namespace CleanArchitecture.Domain.Tests.CommandHandler.User.UpdateUser;
@ -69,8 +69,8 @@ public sealed class UpdateUserCommandHandlerTests
UserRole.User);
_fixture.UserRepository
.Setup(x => x.GetByEmailAsync(command.Email))
.ReturnsAsync(new Entities.User(
.GetByEmailAsync(command.Email)
.Returns(new Entities.User(
Guid.NewGuid(),
command.Email,
"Some",

View File

@ -2,7 +2,7 @@ using System;
using CleanArchitecture.Domain.Commands.Users.UpdateUser;
using CleanArchitecture.Domain.Enums;
using CleanArchitecture.Domain.Interfaces.Repositories;
using Moq;
using NSubstitute;
namespace CleanArchitecture.Domain.Tests.CommandHandler.User.UpdateUser;
@ -10,18 +10,18 @@ public sealed class UpdateUserCommandTestFixture : CommandHandlerFixtureBase
{
public UpdateUserCommandTestFixture()
{
UserRepository = new Mock<IUserRepository>();
UserRepository = Substitute.For<IUserRepository>();
CommandHandler = new UpdateUserCommandHandler(
Bus.Object,
UnitOfWork.Object,
NotificationHandler.Object,
UserRepository.Object,
User.Object);
Bus,
UnitOfWork,
NotificationHandler,
UserRepository,
User);
}
public UpdateUserCommandHandler CommandHandler { get; }
public Mock<IUserRepository> UserRepository { get; }
public IUserRepository UserRepository { get; }
public Entities.User SetupUser()
{
@ -34,8 +34,8 @@ public sealed class UpdateUserCommandTestFixture : CommandHandlerFixtureBase
UserRole.User);
UserRepository
.Setup(x => x.GetByIdAsync(It.Is<Guid>(y => y == user.Id)))
.ReturnsAsync(user);
.GetByIdAsync(Arg.Is<Guid>(y => y == user.Id))
.Returns(user);
return user;
}

View File

@ -4,7 +4,7 @@ using CleanArchitecture.Domain.DomainEvents;
using CleanArchitecture.Domain.Enums;
using CleanArchitecture.Domain.Interfaces;
using CleanArchitecture.Domain.Notifications;
using Moq;
using NSubstitute;
namespace CleanArchitecture.Domain.Tests;
@ -12,46 +12,40 @@ public class CommandHandlerFixtureBase
{
protected CommandHandlerFixtureBase()
{
Bus = new Mock<IMediatorHandler>();
UnitOfWork = new Mock<IUnitOfWork>();
NotificationHandler = new Mock<DomainNotificationHandler>();
User = new Mock<IUser>();
Bus = Substitute.For<IMediatorHandler>();
UnitOfWork = Substitute.For<IUnitOfWork>();
NotificationHandler = Substitute.For<DomainNotificationHandler>();
User = Substitute.For<IUser>();
User.Setup(x => x.GetUserId()).Returns(Guid.NewGuid());
User.Setup(x => x.GetUserRole()).Returns(UserRole.Admin);
User.GetUserId().Returns(Guid.NewGuid());
User.GetUserRole().Returns(UserRole.Admin);
UnitOfWork.Setup(unit => unit.CommitAsync()).ReturnsAsync(true);
UnitOfWork.CommitAsync().Returns(true);
}
protected Mock<IMediatorHandler> Bus { get; }
protected Mock<IUnitOfWork> UnitOfWork { get; }
protected Mock<DomainNotificationHandler> NotificationHandler { get; }
protected Mock<IUser> User { get; }
protected IMediatorHandler Bus { get; }
protected IUnitOfWork UnitOfWork { get; }
protected DomainNotificationHandler NotificationHandler { get; }
protected IUser User { get; }
public CommandHandlerFixtureBase VerifyExistingNotification(string errorCode, string message)
{
Bus.Verify(
bus => bus.RaiseEventAsync(
It.Is<DomainNotification>(not => not.Code == errorCode && not.Value == message)),
Times.Once);
Bus.Received(1).RaiseEventAsync(
Arg.Is<DomainNotification>(not => not.Code == errorCode && not.Value == message));
return this;
}
public CommandHandlerFixtureBase VerifyAnyDomainNotification()
{
Bus.Verify(
bus => bus.RaiseEventAsync(It.IsAny<DomainNotification>()),
Times.Once);
Bus.Received(1).RaiseEventAsync(Arg.Any<DomainNotification>());
return this;
}
public CommandHandlerFixtureBase VerifyNoDomainNotification()
{
Bus.Verify(
bus => bus.RaiseEventAsync(It.IsAny<DomainNotification>()),
Times.Never);
Bus.DidNotReceive().RaiseEventAsync(Arg.Any<DomainNotification>());
return this;
}
@ -59,39 +53,37 @@ public class CommandHandlerFixtureBase
public CommandHandlerFixtureBase VerifyNoRaisedEvent<TEvent>()
where TEvent : DomainEvent
{
Bus.Verify(
bus => bus.RaiseEventAsync(It.IsAny<TEvent>()),
Times.Never);
Bus.DidNotReceive().RaiseEventAsync(Arg.Any<TEvent>());
return this;
}
public CommandHandlerFixtureBase VerifyNoRaisedEvent<TEvent>(Expression<Func<TEvent, bool>> checkFunction)
public CommandHandlerFixtureBase VerifyNoRaisedEvent<TEvent>(Expression<Predicate<TEvent>> checkFunction)
where TEvent : DomainEvent
{
Bus.Verify(bus => bus.RaiseEventAsync(It.Is(checkFunction)), Times.Never);
Bus.DidNotReceive().RaiseEventAsync(Arg.Is(checkFunction));
return this;
}
public CommandHandlerFixtureBase VerifyNoCommit()
{
UnitOfWork.Verify(unit => unit.CommitAsync(), Times.Never);
UnitOfWork.DidNotReceive().CommitAsync();
return this;
}
public CommandHandlerFixtureBase VerifyCommit()
{
UnitOfWork.Verify(unit => unit.CommitAsync(), Times.Once);
UnitOfWork.Received(1).CommitAsync();
return this;
}
public CommandHandlerFixtureBase VerifyRaisedEvent<TEvent>(Expression<Func<TEvent, bool>> checkFunction)
public CommandHandlerFixtureBase VerifyRaisedEvent<TEvent>(Expression<Predicate<TEvent>> checkFunction)
where TEvent : DomainEvent
{
Bus.Verify(bus => bus.RaiseEventAsync(It.Is(checkFunction)), Times.Once);
Bus.Received(1).RaiseEventAsync(Arg.Is(checkFunction));
return this;
}

View File

@ -9,9 +9,11 @@
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="FluentValidation" Version="11.6.0" />
<PackageReference Include="MediatR" Version="12.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.1" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.32.1" />
</ItemGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>

View File

@ -9,8 +9,8 @@
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.11.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.0" />
<PackageReference Include="NSubstitute" Version="5.0.0" />
<PackageReference Include="xunit" Version="2.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@ -1,12 +1,11 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using CleanArchitecture.Domain.Commands.Users.DeleteUser;
using CleanArchitecture.Domain.DomainEvents;
using CleanArchitecture.Domain.Events.User;
using CleanArchitecture.Domain.Notifications;
using MediatR;
using Moq;
using NSubstitute;
using Xunit;
namespace CleanArchitecture.Infrastructure.Tests;
@ -16,10 +15,10 @@ public sealed class InMemoryBusTests
[Fact]
public async Task InMemoryBus_Should_Publish_When_Not_DomainNotification()
{
var mediator = new Mock<IMediator>();
var domainEventStore = new Mock<IDomainEventStore>();
var mediator = Substitute.For<IMediator>();
var domainEventStore = Substitute.For<IDomainEventStore>();
var inMemoryBus = new InMemoryBus(mediator.Object, domainEventStore.Object);
var inMemoryBus = new InMemoryBus(mediator, domainEventStore);
const string key = "Key";
const string value = "Value";
@ -29,36 +28,36 @@ public sealed class InMemoryBusTests
await inMemoryBus.RaiseEventAsync(domainEvent);
mediator.Verify(x => x.Publish(domainEvent, CancellationToken.None), Times.Once);
await mediator.Received(1).Publish(Arg.Is<DomainNotification>(x => x.Equals(domainEvent)), default);
}
[Fact]
public async Task InMemoryBus_Should_Save_And_Publish_When_DomainNotification()
{
var mediator = new Mock<IMediator>();
var domainEventStore = new Mock<IDomainEventStore>();
var mediator = Substitute.For<IMediator>();
var domainEventStore = Substitute.For<IDomainEventStore>();
var inMemoryBus = new InMemoryBus(mediator.Object, domainEventStore.Object);
var inMemoryBus = new InMemoryBus(mediator, domainEventStore);
var userDeletedEvent = new UserDeletedEvent(Guid.NewGuid());
await inMemoryBus.RaiseEventAsync(userDeletedEvent);
mediator.Verify(x => x.Publish(userDeletedEvent, CancellationToken.None), Times.Once);
await mediator.Received(1).Publish(Arg.Is<UserDeletedEvent>(x => x.Equals(userDeletedEvent)), default);
}
[Fact]
public async Task InMemoryBus_Should_Send_Command_Async()
{
var mediator = new Mock<IMediator>();
var domainEventStore = new Mock<IDomainEventStore>();
var mediator = Substitute.For<IMediator>();
var domainEventStore = Substitute.For<IDomainEventStore>();
var inMemoryBus = new InMemoryBus(mediator.Object, domainEventStore.Object);
var inMemoryBus = new InMemoryBus(mediator, domainEventStore);
var deleteUserCommand = new DeleteUserCommand(Guid.NewGuid());
await inMemoryBus.SendCommandAsync(deleteUserCommand);
mediator.Verify(x => x.Send(deleteUserCommand, CancellationToken.None), Times.Once);
await mediator.Received(1).Send(Arg.Is<DeleteUserCommand>(x => x.Equals(deleteUserCommand)), default);
}
}

View File

@ -6,7 +6,7 @@ using CleanArchitecture.Infrastructure.Tests.Fixtures;
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Moq;
using NSubstitute;
using Xunit;
namespace CleanArchitecture.Infrastructure.Tests;
@ -17,14 +17,12 @@ public sealed class UnitOfWorkTests
public async Task Should_Commit_Async_Returns_True()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>();
var dbContextMock = new Mock<ApplicationDbContext>(options.Options);
var loggerMock = new Mock<ILogger<UnitOfWork<ApplicationDbContext>>>();
var dbContextMock = Substitute.For<ApplicationDbContext>(options.Options);
var loggerMock = Substitute.For<ILogger<UnitOfWork<ApplicationDbContext>>>();
dbContextMock
.Setup(x => x.SaveChangesAsync(CancellationToken.None))
.Returns(Task.FromResult(1));
dbContextMock.SaveChangesAsync(CancellationToken.None).Returns(Task.FromResult(1));
var unitOfWork = UnitOfWorkTestFixture.GetUnitOfWork(dbContextMock.Object, loggerMock.Object);
var unitOfWork = UnitOfWorkTestFixture.GetUnitOfWork(dbContextMock, loggerMock);
var result = await unitOfWork.CommitAsync();
@ -35,14 +33,14 @@ public sealed class UnitOfWorkTests
public async Task Should_Commit_Async_Returns_False()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>();
var dbContextMock = new Mock<ApplicationDbContext>(options.Options);
var loggerMock = new Mock<ILogger<UnitOfWork<ApplicationDbContext>>>();
var dbContextMock = Substitute.For<ApplicationDbContext>(options.Options);
var loggerMock = Substitute.For<ILogger<UnitOfWork<ApplicationDbContext>>>();
dbContextMock
.Setup(x => x.SaveChangesAsync(CancellationToken.None))
.Throws(new DbUpdateException("Boom", new Exception("it broke")));
.When(x => x.SaveChangesAsync(CancellationToken.None))
.Do(x => throw new DbUpdateException("Boom", new Exception("it broke")));
var unitOfWork = UnitOfWorkTestFixture.GetUnitOfWork(dbContextMock.Object, loggerMock.Object);
var unitOfWork = UnitOfWorkTestFixture.GetUnitOfWork(dbContextMock, loggerMock);
var result = await unitOfWork.CommitAsync();
@ -53,14 +51,14 @@ public sealed class UnitOfWorkTests
public async Task Should_Throw_Exception_When_Commiting_With_DbUpdateException()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>();
var dbContextMock = new Mock<ApplicationDbContext>(options.Options);
var loggerMock = new Mock<ILogger<UnitOfWork<ApplicationDbContext>>>();
var dbContextMock = Substitute.For<ApplicationDbContext>(options.Options);
var loggerMock = Substitute.For<ILogger<UnitOfWork<ApplicationDbContext>>>();
dbContextMock
.Setup(x => x.SaveChangesAsync(CancellationToken.None))
.Throws(new Exception("boom"));
.When(x => x.SaveChangesAsync(CancellationToken.None))
.Do(x => throw new Exception("Boom"));
var unitOfWork = UnitOfWorkTestFixture.GetUnitOfWork(dbContextMock.Object, loggerMock.Object);
var unitOfWork = UnitOfWorkTestFixture.GetUnitOfWork(dbContextMock, loggerMock);
Func<Task> throwsAction = async () => await unitOfWork.CommitAsync();

View File

@ -11,10 +11,10 @@
<ItemGroup>
<PackageReference Include="MediatR" Version="12.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.9">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="7.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.10">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@ -9,11 +9,11 @@
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.11.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.9" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.9" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.10" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="7.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="7.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.10" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.0" />
<PackageReference Include="xunit" Version="2.5.0" />
<PackageReference Include="Xunit.Priority" Version="1.1.6" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0">

View File

@ -16,8 +16,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.23.4" />
<PackageReference Include="Google.Protobuf.Tools" Version="3.23.4" />
<PackageReference Include="Google.Protobuf" Version="3.24.0" />
<PackageReference Include="Google.Protobuf.Tools" Version="3.24.0" />
<PackageReference Include="Grpc.AspNetCore" Version="2.55.0" />
</ItemGroup>

View File

@ -9,9 +9,9 @@
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.11.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
<PackageReference Include="MockQueryable.Moq" Version="7.0.0" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.0" />
<PackageReference Include="MockQueryable.NSubstitute" Version="7.0.0" />
<PackageReference Include="NSubstitute" Version="5.0.0" />
<PackageReference Include="xunit" Version="2.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@ -1,12 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CleanArchitecture.Application.gRPC;
using CleanArchitecture.Domain.Entities;
using CleanArchitecture.Domain.Enums;
using CleanArchitecture.Domain.Interfaces.Repositories;
using MockQueryable.Moq;
using Moq;
using MockQueryable.NSubstitute;
using NSubstitute;
namespace CleanArchitecture.gRPC.Tests.Fixtures;
@ -39,16 +38,14 @@ public sealed class UserTestsFixture
UserRole.User)
};
var queryable = ExistingUsers.AsQueryable().BuildMock();
var queryable = ExistingUsers.BuildMock();
UserRepository
.Setup(repository => repository.GetAllNoTracking())
.Returns(queryable);
UserRepository.GetAllNoTracking().Returns(queryable);
UsersApiImplementation = new UsersApiImplementation(UserRepository.Object);
UsersApiImplementation = new UsersApiImplementation(UserRepository);
}
private Mock<IUserRepository> UserRepository { get; } = new();
private IUserRepository UserRepository { get; } = Substitute.For<IUserRepository>();
public UsersApiImplementation UsersApiImplementation { get; }