diff --git a/Directory.Packages.props b/Directory.Packages.props index 3056a45bf..eee2f424b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -36,7 +36,6 @@ - @@ -61,7 +60,6 @@ - diff --git a/src/DevBetterWeb.Core/Services/MemberAddBillingActivityService.cs b/src/DevBetterWeb.Core/Services/MemberAddBillingActivityService.cs index 91a2598f1..5e2553f3d 100644 --- a/src/DevBetterWeb.Core/Services/MemberAddBillingActivityService.cs +++ b/src/DevBetterWeb.Core/Services/MemberAddBillingActivityService.cs @@ -10,7 +10,7 @@ public class MemberAddBillingActivityService : IMemberAddBillingActivityService { private readonly IRepository _memberRepository; private readonly IMemberLookupService _memberLookupService; - + public MemberAddBillingActivityService(IRepository memberRepository, IMemberLookupService memberLookup) { @@ -18,6 +18,13 @@ public MemberAddBillingActivityService(IRepository memberRepository, _memberLookupService = memberLookup; } +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public MemberAddBillingActivityService() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + + } + /// /// This should only be called after a member has registered and been created. /// diff --git a/src/DevBetterWeb.Web/Views/Home/Index.cshtml b/src/DevBetterWeb.Web/Views/Home/Index.cshtml index 88c6431e9..ef3aad6c8 100644 --- a/src/DevBetterWeb.Web/Views/Home/Index.cshtml +++ b/src/DevBetterWeb.Web/Views/Home/Index.cshtml @@ -369,7 +369,6 @@ Join the devBetter group coaching program today and get immediate access to all recorded sessions, the Discord channel, the web site resources, the private GitHub, the private Stack Overflow team, and more! -

diff --git a/tests/DevBetterWeb.Tests/DevBetterWeb.Tests.csproj b/tests/DevBetterWeb.Tests/DevBetterWeb.Tests.csproj index b0a4a389f..d585a35ff 100644 --- a/tests/DevBetterWeb.Tests/DevBetterWeb.Tests.csproj +++ b/tests/DevBetterWeb.Tests/DevBetterWeb.Tests.csproj @@ -49,7 +49,6 @@ - diff --git a/tests/DevBetterWeb.Tests/Services/AlumniGraduationServiceTests/CheckIfAnyMemberGraduating.cs b/tests/DevBetterWeb.Tests/Services/AlumniGraduationServiceTests/CheckIfAnyMemberGraduating.cs index 2f91ae17b..009556ab5 100644 --- a/tests/DevBetterWeb.Tests/Services/AlumniGraduationServiceTests/CheckIfAnyMemberGraduating.cs +++ b/tests/DevBetterWeb.Tests/Services/AlumniGraduationServiceTests/CheckIfAnyMemberGraduating.cs @@ -5,17 +5,17 @@ using DevBetterWeb.Core.Interfaces; using DevBetterWeb.Core.ValueObjects; using DevBetterWeb.Infrastructure.Services; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.Tests.Services.AlumniGraduationServiceTests; public class CheckIfAnyMemberGraduating { - private readonly Mock userLookupService; - private readonly Mock> repository; - private readonly Mock graduationCommunications; - private readonly Mock userManager; + private readonly IUserLookupService userLookupService; + private readonly IRepository repository; + private readonly IGraduationCommunicationsService graduationCommunications; + private readonly IUserRoleManager userManager; private const int DAYS_IN_TWO_YEARS = 365 * 2; @@ -23,11 +23,11 @@ public class CheckIfAnyMemberGraduating public CheckIfAnyMemberGraduating() { - userLookupService = new Mock(); - repository = new Mock>(); - graduationCommunications = new Mock(); - userManager = new Mock(); - service = new AlumniGraduationService(userLookupService.Object, repository.Object, graduationCommunications.Object, userManager.Object); + userLookupService = Substitute.For(); + repository = Substitute.For>(); + graduationCommunications = Substitute.For(); + userManager = Substitute.For(); + service = new AlumniGraduationService(userLookupService, repository, graduationCommunications, userManager); } [Fact] @@ -47,7 +47,7 @@ public async Task ReturnsSameListGivenListWithAllMembersGraduating() var graduatingMember = GetGraduatingMember(); testlist.Add(graduatingMember); - userLookupService.Setup(u => u.FindUserIsAlumniByUserIdAsync(graduatingMember.UserId)).ReturnsAsync(false); + userLookupService.FindUserIsAlumniByUserIdAsync(graduatingMember.UserId).Returns(Task.FromResult(false)); var list = await service.CheckIfAnyMemberGraduating(testlist); @@ -65,8 +65,8 @@ public async Task ReturnsOnlyGraduatingMembersGivenListWithSomeMembersGraduating var nonGraduatingMember = GetNonGraduatingMember(); testlist.Add(nonGraduatingMember); - userLookupService.Setup(u => u.FindUserIsAlumniByUserIdAsync(graduatingMember.UserId)).ReturnsAsync(false); - + userLookupService.FindUserIsAlumniByUserIdAsync(graduatingMember.UserId).Returns(Task.FromResult(false)); + var list = await service.CheckIfAnyMemberGraduating(testlist); Assert.Contains(graduatingMember, list); @@ -91,8 +91,8 @@ public async Task ReturnsEmptyListGivenListOfAlumni() var testlist = new List(); var alum = GetGraduatingMember(); testlist.Add(alum); - - userLookupService.Setup(u => u.FindUserIsAlumniByUserIdAsync(alum.UserId)).ReturnsAsync(true); + + userLookupService.FindUserIsAlumniByUserIdAsync(alum.UserId).Returns(Task.FromResult(true)); var list = await service.CheckIfAnyMemberGraduating(testlist); @@ -109,7 +109,7 @@ public async Task ReturnsEmptyListGivenListWithMemberOneDayFromGraduation() member.MemberSubscriptions.Add(nearGraduationSubscription); testlist.Add(member); - userLookupService.Setup(u => u.FindUserIsAlumniByUserIdAsync(member.UserId)).ReturnsAsync(false); + userLookupService.FindUserIsAlumniByUserIdAsync(member.UserId).Returns(Task.FromResult(false)); var list = await service.CheckIfAnyMemberGraduating(testlist); diff --git a/tests/DevBetterWeb.Tests/Services/DailyCheckPingServiceTests/CheckIfAnyActiveInvitationsRequireAdminPing.cs b/tests/DevBetterWeb.Tests/Services/DailyCheckPingServiceTests/CheckIfAnyActiveInvitationsRequireAdminPing.cs index 8a4870e18..55e9ceeea 100644 --- a/tests/DevBetterWeb.Tests/Services/DailyCheckPingServiceTests/CheckIfAnyActiveInvitationsRequireAdminPing.cs +++ b/tests/DevBetterWeb.Tests/Services/DailyCheckPingServiceTests/CheckIfAnyActiveInvitationsRequireAdminPing.cs @@ -4,17 +4,17 @@ using DevBetterWeb.Infrastructure.Identity.Data; using DevBetterWeb.Infrastructure.Services; using Microsoft.AspNetCore.Identity; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.Tests.Services.DailyCheckPingServiceTests; public class CheckIfAnyActiveInvitationsRequireAdminPing { - private readonly Mock> _repository = new(); - private readonly Mock> _memberRepository = new(); - private readonly Mock _emailService = new(); - private readonly Mock> _userManager; + private readonly IRepository _repository; + private readonly IRepository _memberRepository; + private readonly IEmailService _emailService; + private readonly UserManager _userManager; private DailyCheckPingService _service; @@ -23,9 +23,12 @@ public class CheckIfAnyActiveInvitationsRequireAdminPing public CheckIfAnyActiveInvitationsRequireAdminPing() { - var store = new Mock>(); - _userManager = new Mock>(store.Object, null, null, null, null, null, null, null, null); - _service = new DailyCheckPingService(_repository.Object, _memberRepository.Object, _emailService.Object, _userManager.Object); + var store = Substitute.For>(); + _userManager = Substitute.For>(store, null, null, null, null, null, null, null, null); + _repository = Substitute.For>(); + _memberRepository = Substitute.For>(); + _emailService = Substitute.For(); + _service = new DailyCheckPingService(_repository, _memberRepository, _emailService, _userManager); } [Fact] diff --git a/tests/DevBetterWeb.Tests/Services/DailyCheckPingServiceTests/CheckIfAnyActiveInvitationsRequireUserPing.cs b/tests/DevBetterWeb.Tests/Services/DailyCheckPingServiceTests/CheckIfAnyActiveInvitationsRequireUserPing.cs index 6cebbbfa5..38568c6f3 100644 --- a/tests/DevBetterWeb.Tests/Services/DailyCheckPingServiceTests/CheckIfAnyActiveInvitationsRequireUserPing.cs +++ b/tests/DevBetterWeb.Tests/Services/DailyCheckPingServiceTests/CheckIfAnyActiveInvitationsRequireUserPing.cs @@ -4,17 +4,17 @@ using DevBetterWeb.Infrastructure.Identity.Data; using DevBetterWeb.Infrastructure.Services; using Microsoft.AspNetCore.Identity; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.Tests.Services.DailyCheckPingServiceTests; public class CheckIfAnyActiveInvitationsRequireUserPing { - private readonly Mock> _repository = new(); - private readonly Mock> _membrRepository = new(); - private readonly Mock _emailService = new(); - private readonly Mock> _userManager; + private readonly IRepository _repository; + private readonly IRepository _memberRepository; + private readonly IEmailService _emailService; + private readonly UserManager _userManager; private DailyCheckPingService _service; @@ -23,10 +23,12 @@ public class CheckIfAnyActiveInvitationsRequireUserPing public CheckIfAnyActiveInvitationsRequireUserPing() { - var store = new Mock>(); - _userManager = new Mock>(store.Object, null, null, null, null, null, null, null, null); - - _service = new DailyCheckPingService(_repository.Object, _membrRepository.Object, _emailService.Object, _userManager.Object); + var store = Substitute.For>(); + _userManager = Substitute.For>(store, null, null, null, null, null, null, null, null); + _repository = Substitute.For>(); + _memberRepository = Substitute.For>(); + _emailService = Substitute.For(); + _service = new DailyCheckPingService(_repository, _memberRepository, _emailService, _userManager); } [Fact] diff --git a/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/MemberSubscriptionCancellationServiceTest.cs b/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/MemberSubscriptionCancellationServiceTest.cs index 6d98a92ab..bcc993c8c 100644 --- a/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/MemberSubscriptionCancellationServiceTest.cs +++ b/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/MemberSubscriptionCancellationServiceTest.cs @@ -1,30 +1,30 @@ using DevBetterWeb.Core.Entities; using DevBetterWeb.Core.Interfaces; using DevBetterWeb.Core.Services; -using Moq; +using NSubstitute; namespace DevBetterWeb.Tests.Services.MemberSubscriptionCancellationServiceTests; public class MemberSubscriptionCancellationServiceTest { - internal readonly Mock _userRoleMembershipService; - internal readonly Mock _emailService; - internal readonly Mock _userLookup; - internal readonly Mock _memberLookup; - internal readonly Mock> _memberRepository; - internal readonly Mock _subscriptionPeriodCalculationsService; + internal readonly IUserRoleMembershipService _userRoleMembershipService; + internal readonly IEmailService _emailService; + internal readonly IUserLookupService _userLookup; + internal readonly IMemberLookupService _memberLookup; + internal readonly IRepository _memberRepository; + internal readonly IMemberSubscriptionPeriodCalculationsService _subscriptionPeriodCalculationsService; internal readonly IMemberCancellationService _memberCancellationService; public MemberSubscriptionCancellationServiceTest() { - _userRoleMembershipService = new Mock(); - _emailService = new Mock(); - _userLookup = new Mock(); - _memberLookup = new Mock(); - _memberRepository = new Mock>(); - _subscriptionPeriodCalculationsService = new Mock(); - _memberCancellationService = new MemberSubscriptionCancellationService(_userRoleMembershipService.Object, - _emailService.Object, _userLookup.Object, _memberLookup.Object, _memberRepository.Object, _subscriptionPeriodCalculationsService.Object); + _userRoleMembershipService = Substitute.For(); + _emailService = Substitute.For(); + _userLookup = Substitute.For(); + _memberLookup = Substitute.For(); + _memberRepository = Substitute.For>(); + _subscriptionPeriodCalculationsService = Substitute.For(); + _memberCancellationService = new MemberSubscriptionCancellationService(_userRoleMembershipService, + _emailService, _userLookup, _memberLookup, _memberRepository, _subscriptionPeriodCalculationsService); } } diff --git a/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/RemoveUserFromMemberRoleAsync.cs b/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/RemoveUserFromMemberRoleAsync.cs index dc50d7b18..907c165c7 100644 --- a/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/RemoveUserFromMemberRoleAsync.cs +++ b/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/RemoveUserFromMemberRoleAsync.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; using DevBetterWeb.Core; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.Tests.Services.MemberSubscriptionCancellationServiceTests; @@ -13,11 +13,11 @@ public class RemoveUserFromMemberRoleAsync : MemberSubscriptionCancellationServi [Fact] public async Task RemovesUserFromMemberRole() { - _userLookup.Setup(u => u.FindUserIdByEmailAsync(_email)).ReturnsAsync(_userId); + _userLookup.FindUserIdByEmailAsync(_email).Returns(Task.FromResult(_userId)); await _memberCancellationService.RemoveUserFromMemberRoleAsync(_email); - _userRoleMembershipService.Verify(u => u.RemoveUserFromRoleByRoleNameAsync(_userId, Constants.MEMBER_ROLE_NAME), Times.Once); + await _userRoleMembershipService.Received(1).RemoveUserFromRoleByRoleNameAsync(_userId, Constants.MEMBER_ROLE_NAME); } } diff --git a/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/SendCancellationEmailAsync.cs b/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/SendCancellationEmailAsync.cs index 3ce84ba66..6810f5ab9 100644 --- a/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/SendCancellationEmailAsync.cs +++ b/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/SendCancellationEmailAsync.cs @@ -1,5 +1,5 @@ using System.Threading.Tasks; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.Tests.Services.MemberSubscriptionCancellationServiceTests; @@ -13,7 +13,7 @@ public async Task SendsEmail() { await _memberCancellationService.SendCancellationEmailAsync(_email); - _emailService.Verify(e => e.SendEmailAsync(_email, It.IsAny(), It.IsAny())); + await _emailService.Received().SendEmailAsync(_email, Arg.Any(), Arg.Any()); } } diff --git a/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/SendFutureCancellationEmailAsync.cs b/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/SendFutureCancellationEmailAsync.cs index fd1da50b6..8e567644f 100644 --- a/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/SendFutureCancellationEmailAsync.cs +++ b/tests/DevBetterWeb.Tests/Services/MemberSubscriptionCancellationServiceTests/SendFutureCancellationEmailAsync.cs @@ -3,24 +3,31 @@ using System.Threading.Tasks; using DevBetterWeb.Core.Entities; using DevBetterWeb.Core.Specs; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.Tests.Services.MemberSubscriptionCancellationServiceTests; public class SendFutureCancellationEmailAsync : MemberSubscriptionCancellationServiceTest { - private readonly string _email = "TestEmail"; - private readonly DateTime _date = new DateTime(1, 1, 1); + private readonly string _email = "TestEmail"; + private readonly DateTime _date = new DateTime(1, 1, 1); - [Fact] - public async Task SendsEmail() - { - _memberRepository.Setup(s => s.FirstOrDefaultAsync(It.IsAny(), CancellationToken.None)).ReturnsAsync(new Member()); - _subscriptionPeriodCalculationsService.Setup(s => s.GetCurrentSubscriptionEndDate(It.IsAny())).Returns(_date); + [Fact] + public async Task SendsEmail() + { + _memberRepository.FirstOrDefaultAsync( + Arg.Any(), + CancellationToken.None)! + .Returns(Task.FromResult(new Member())); - await _memberCancellationService.SendFutureCancellationEmailAsync(_email); + _subscriptionPeriodCalculationsService.GetCurrentSubscriptionEndDate( + Arg.Any()) + .Returns(_date); - _emailService.Verify(e => e.SendEmailAsync(_email, It.IsAny(), It.IsAny())); - } + await _memberCancellationService.SendFutureCancellationEmailAsync(_email); + + await _emailService.Received() + .SendEmailAsync(_email, Arg.Any(), Arg.Any()); + } } diff --git a/tests/DevBetterWeb.Tests/Services/MemberSubscriptionEndedAdminEmailServiceTests/SendMemberSubscriptionEndedEmailAsync.cs b/tests/DevBetterWeb.Tests/Services/MemberSubscriptionEndedAdminEmailServiceTests/SendMemberSubscriptionEndedEmailAsync.cs index ef23fa163..2969b7744 100644 --- a/tests/DevBetterWeb.Tests/Services/MemberSubscriptionEndedAdminEmailServiceTests/SendMemberSubscriptionEndedEmailAsync.cs +++ b/tests/DevBetterWeb.Tests/Services/MemberSubscriptionEndedAdminEmailServiceTests/SendMemberSubscriptionEndedEmailAsync.cs @@ -6,39 +6,41 @@ using DevBetterWeb.Infrastructure.Identity.Data; using DevBetterWeb.Infrastructure.Services; using Microsoft.AspNetCore.Identity; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.Tests.Services.MemberSubscriptionEndedAdminEmailServiceTests; public class SendMemberSubscriptionEndedEmailAsync { - private readonly MemberSubscriptionEndedAdminEmailService _memberSubscriptionEndedAdminEmailService; + private readonly MemberSubscriptionEndedAdminEmailService _memberSubscriptionEndedAdminEmailService; - private readonly Mock> _userManager; - private readonly Mock _emailService; - private readonly Mock _memberLookup; + private readonly UserManager _userManager; + private readonly IEmailService _emailService; + private readonly IMemberLookupService _memberLookup; - public SendMemberSubscriptionEndedEmailAsync() - { - var store = new Mock>(); - _userManager = new Mock>(store.Object, null, null, null, null, null, null, null, null); - _emailService = new Mock(); - _memberLookup = new Mock(); - _memberSubscriptionEndedAdminEmailService = new MemberSubscriptionEndedAdminEmailService( - _userManager.Object, _emailService.Object, _memberLookup.Object); - } + public SendMemberSubscriptionEndedEmailAsync() + { + var store = Substitute.For>(); + _userManager = Substitute.For>(store, null, null, null, null, null, null, null, null); + _emailService = Substitute.For(); + _memberLookup = Substitute.For(); + _memberSubscriptionEndedAdminEmailService = new MemberSubscriptionEndedAdminEmailService( + _userManager, _emailService, _memberLookup); + } - [Fact] - public async Task SendsEmail() - { - _memberLookup.Setup(m => m.GetMemberByEmailAsync(It.IsAny())).ReturnsAsync(new Mock().Object); - _userManager.Setup(u => u.GetUsersInRoleAsync(AuthConstants.Roles.ADMINISTRATORS)).ReturnsAsync( - new List { new Mock().Object, new Mock().Object }); + [Fact] + public async Task SendsEmail() + { + _memberLookup.GetMemberByEmailAsync(Arg.Any()) + .Returns(Task.FromResult(Substitute.For())); + _userManager.GetUsersInRoleAsync(AuthConstants.Roles.ADMINISTRATORS) + .Returns(Task.FromResult>(new List { Substitute.For(), Substitute.For() })); - string testEmail = "TestEmail"; - await _memberSubscriptionEndedAdminEmailService.SendMemberSubscriptionEndedEmailAsync(testEmail, null); + string testEmail = "TestEmail"; + await _memberSubscriptionEndedAdminEmailService.SendMemberSubscriptionEndedEmailAsync(testEmail, null); - _emailService.Verify(e => e.SendEmailAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); - } + await _emailService.Received(2) + .SendEmailAsync(Arg.Any(), Arg.Any(), Arg.Any()); + } } diff --git a/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/CreateInvitation.cs b/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/CreateInvitation.cs index 4e0485bd1..cfef99af9 100644 --- a/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/CreateInvitation.cs +++ b/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/CreateInvitation.cs @@ -3,35 +3,36 @@ using DevBetterWeb.Core.Entities; using DevBetterWeb.Core.Interfaces; using DevBetterWeb.Core.Services; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.Tests.Services.NewMemberServiceTests; public class CreateInvitation { - private readonly Mock> _memberRepository = new(); - private readonly Mock> _invitationRepository = new(); - private readonly Mock _userRoleMembershipService = new(); - private readonly Mock _paymentHandlerSubscription = new(); - private readonly Mock _emailService = new(); - private readonly Mock _memberRegistrationService = new(); - private readonly Mock> _logger = new(); - - private readonly INewMemberService _newMemberService; - + private readonly IRepository _invitationRepository = Substitute.For>(); + private readonly IUserRoleMembershipService _userRoleMembershipService = Substitute.For(); + private readonly IPaymentHandlerSubscription _paymentHandlerSubscription = + Substitute.For(); + private readonly IEmailService _emailService = Substitute.For(); + private readonly IMemberRegistrationService _memberRegistrationService = Substitute.For(); + private readonly IAppLogger _logger = Substitute.For>(); + private readonly INewMemberService _newMemberService; + private readonly MemberAddBillingActivityService _memberAddBillingActivityService = + Substitute.For(); + private readonly string _email = "TestEmail"; private readonly string _subscriptionId = "TestSubscriptionId"; public CreateInvitation() { - _newMemberService = new NewMemberService(_invitationRepository.Object, - _userRoleMembershipService.Object, - _paymentHandlerSubscription.Object, - _emailService.Object, - _memberRegistrationService.Object, - _logger.Object, - null!); // TODO: Add dependency + _newMemberService = new NewMemberService(_invitationRepository, + _userRoleMembershipService, + _paymentHandlerSubscription, + _emailService, + _memberRegistrationService, + _logger, + _memberAddBillingActivityService); } @@ -43,6 +44,6 @@ public async Task CreatesInvitationWithGivenEmailAndEventId() Assert.Equal(_email, invitation.Email); Assert.Equal(_subscriptionId, invitation.PaymentHandlerSubscriptionId); - _invitationRepository.Verify(r => r.AddAsync(invitation, CancellationToken.None), Times.Once); + await _invitationRepository.Received(1).AddAsync(invitation, CancellationToken.None); } } diff --git a/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/MemberSetup.cs b/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/MemberSetup.cs index 694ca7a67..c02ee820b 100644 --- a/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/MemberSetup.cs +++ b/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/MemberSetup.cs @@ -5,22 +5,25 @@ using DevBetterWeb.Core.Interfaces; using DevBetterWeb.Core.Services; using DevBetterWeb.Core.Specs; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.Tests.Services.NewMemberServiceTests; public class MemberSetup { - private readonly Mock> _memberRepository = new(); - private readonly Mock> _invitationRepository = new(); - private readonly Mock _userRoleMembershipService = new(); - private readonly Mock _paymentHandlerSubscription = new(); - private readonly Mock _emailService = new(); - private readonly Mock _memberRegistrationService = new(); - private readonly Mock> _logger = new(); - private readonly Mock _memberAddBillingActivityService = new(); + private readonly IMemberAddBillingActivityService _memberAddBillingActivityService = Substitute.For(); + private readonly IRepository _memberRepository = Substitute.For>(); + private readonly IRepository _invitationRepository = Substitute.For>(); + private readonly IUserRoleMembershipService _userRoleMembershipService = Substitute.For(); + private readonly IPaymentHandlerSubscription _paymentHandlerSubscription = + Substitute.For(); + private readonly IEmailService _emailService = Substitute.For(); + private readonly IMemberRegistrationService _memberRegistrationService = Substitute.For(); + private readonly IAppLogger _logger = Substitute.For>(); + + private readonly INewMemberService _newMemberService; private readonly string _userId = "TestUserId"; @@ -36,13 +39,13 @@ public class MemberSetup public MemberSetup() { - _newMemberService = new NewMemberService(_invitationRepository.Object, - _userRoleMembershipService.Object, - _paymentHandlerSubscription.Object, - _emailService.Object, - _memberRegistrationService.Object, - _logger.Object, - _memberAddBillingActivityService.Object); + _newMemberService = new NewMemberService(_invitationRepository, + _userRoleMembershipService, + _paymentHandlerSubscription, + _emailService, + _memberRegistrationService, + _logger, + _memberAddBillingActivityService); _invitation = new Invitation(_email, _inviteCode, _subscriptionId); } @@ -52,17 +55,18 @@ public async Task SetsUpNewMember() var memberResult = new Member(); var memberId = memberResult.Id; - _invitationRepository.Setup(r => r.FirstOrDefaultAsync(It.IsAny(), CancellationToken.None)).ReturnsAsync(_invitation); - _invitationRepository.Setup(r => r.ListAsync(It.IsAny(), CancellationToken.None)).ReturnsAsync(new List()); - _memberRepository.Setup(r => r.GetByIdAsync(memberId, CancellationToken.None)).ReturnsAsync(memberResult); - _memberRegistrationService.Setup(r => r.RegisterMemberAsync(_userId)).ReturnsAsync(memberResult); + _invitationRepository.FirstOrDefaultAsync(Arg.Any(), CancellationToken.None)!.Returns(Task.FromResult(_invitation)); + _invitationRepository.ListAsync(Arg.Any(), CancellationToken.None).Returns(Task.FromResult(new List()) ); + _memberRepository.GetByIdAsync(memberId, CancellationToken.None)!.Returns(Task.FromResult(memberResult)); + _memberRegistrationService.RegisterMemberAsync(_userId).Returns(Task.FromResult(memberResult)); Member member = await _newMemberService.MemberSetupAsync(_userId, _firstName, _lastName, _inviteCode, ""); Assert.Equal(_firstName, member.FirstName); Assert.Equal(_lastName, member.LastName); - _userRoleMembershipService.Verify(u => u.AddUserToRoleByRoleNameAsync(_userId, _roleName), Times.Once); + await _userRoleMembershipService.Received(1) + .AddUserToRoleByRoleNameAsync(_userId, _roleName); Assert.False(_invitation.Active); } } diff --git a/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/SendRegistrationEmail.cs b/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/SendRegistrationEmail.cs index 0b64f348e..f0e8e171b 100644 --- a/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/SendRegistrationEmail.cs +++ b/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/SendRegistrationEmail.cs @@ -2,20 +2,24 @@ using DevBetterWeb.Core.Entities; using DevBetterWeb.Core.Interfaces; using DevBetterWeb.Core.Services; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.Tests.Services.NewMemberServiceTests; public class SendRegistrationEmail { - private readonly Mock> _memberRepository = new(); - private readonly Mock> _invitationRepository = new(); - private readonly Mock _userRoleMembershipService = new(); - private readonly Mock _paymentHandlerSubscription = new(); - private readonly Mock _emailService = new(); - private readonly Mock _memberRegistrationService = new(); - private readonly Mock> _logger = new(); + private readonly IRepository _memberRepository = Substitute.For>(); + private readonly IRepository _invitationRepository = Substitute.For>(); + private readonly IUserRoleMembershipService _userRoleMembershipService = Substitute.For(); + private readonly IPaymentHandlerSubscription _paymentHandlerSubscription = + Substitute.For(); + private readonly IEmailService _emailService = Substitute.For(); + private readonly IMemberRegistrationService _memberRegistrationService = Substitute.For(); + private readonly IAppLogger _logger = Substitute.For>(); + + private readonly MemberAddBillingActivityService _memberAddBillingActivityService = + Substitute.For(); private readonly INewMemberService _newMemberService; @@ -27,13 +31,13 @@ public class SendRegistrationEmail public SendRegistrationEmail() { - _newMemberService = new NewMemberService(_invitationRepository.Object, - _userRoleMembershipService.Object, - _paymentHandlerSubscription.Object, - _emailService.Object, - _memberRegistrationService.Object, - _logger.Object, - null!); // TODO: Add dependency + _newMemberService = new NewMemberService(_invitationRepository, + _userRoleMembershipService, + _paymentHandlerSubscription, + _emailService, + _memberRegistrationService, + _logger, + _memberAddBillingActivityService); _invitation = new Invitation(_email, _inviteCode, _subscriptionId); } @@ -43,7 +47,8 @@ public async Task SendsRegistrationEmail() { await _newMemberService.SendRegistrationEmailAsync(_invitation); - _emailService.Verify(e => e.SendEmailAsync(_email, It.IsAny(), It.IsAny()), Times.Once); + await _emailService.Received(1) + .SendEmailAsync(_email, Arg.Any(), Arg.Any()); } } diff --git a/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/VerifyValidEmailAndInviteCode.cs b/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/VerifyValidEmailAndInviteCode.cs index 5fa2b737f..880641110 100644 --- a/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/VerifyValidEmailAndInviteCode.cs +++ b/tests/DevBetterWeb.Tests/Services/NewMemberServiceTests/VerifyValidEmailAndInviteCode.cs @@ -4,97 +4,117 @@ using DevBetterWeb.Core.Interfaces; using DevBetterWeb.Core.Services; using DevBetterWeb.Core.Specs; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.Tests.Services.NewMemberServiceTests; public class VerifyValidEmailAndInviteCode { - private readonly Mock> _memberRepository = new(); - private readonly Mock> _invitationRepository = new(); - private readonly Mock _userRoleMembershipService = new(); - private readonly Mock _paymentHandlerSubscription = new(); - private readonly Mock _emailService = new(); - private readonly Mock _memberRegistrationService = new(); - private readonly Mock> _logger = new(); - - private readonly INewMemberService _newMemberService; - - private readonly string _email = "TestEmail"; - private readonly string _inviteCode = "TestInviteCode"; - private readonly string _subscriptionId = "TestSubscriptionId"; - - private readonly string _validEmailAndInviteCodeString = "success"; - private readonly string _invalidEmailString = "Invalid email or invite code: DevBetterWeb.Core.Exceptions.InvalidEmailException"; - private readonly string _invalidInviteCodeString = "Invalid email or invite code: DevBetterWeb.Core.Exceptions.InvitationNotFoundException"; - private readonly string _inactiveInviteString = "Invalid email or invite code: DevBetterWeb.Core.Exceptions.InvitationNotActiveException"; - - public VerifyValidEmailAndInviteCode() - { - _newMemberService = new NewMemberService(_invitationRepository.Object, - _userRoleMembershipService.Object, - _paymentHandlerSubscription.Object, - _emailService.Object, - _memberRegistrationService.Object, - _logger.Object, - null!); // TODO: Add dependency - } - - [Fact] - public async Task ReturnsSuccessGivenValidEmailAndInviteCode() - { - var invitation = new Invitation(_email, _inviteCode, _subscriptionId); - - _invitationRepository.Setup(r => r.FirstOrDefaultAsync(It.IsAny(), CancellationToken.None)).ReturnsAsync(invitation); - - var result = await _newMemberService.VerifyValidEmailAndInviteCodeAsync(_email, _inviteCode); - - _invitationRepository.Verify(r => r.FirstOrDefaultAsync(It.IsAny(), CancellationToken.None), Times.Once); - Assert.Equal(_validEmailAndInviteCodeString, result.Value); - } - - [Fact] - public async Task ReturnsExceptionMessageGivenInvalidEmail() - { - var invitation = new Invitation("", _inviteCode, _subscriptionId); - - _invitationRepository.Setup(r => r.FirstOrDefaultAsync(It.IsAny(), CancellationToken.None)).ReturnsAsync(invitation); - - var result = await _newMemberService.VerifyValidEmailAndInviteCodeAsync(_email, _inviteCode); - - _invitationRepository.Verify(r => r.FirstOrDefaultAsync(It.IsAny(), CancellationToken.None), Times.Once); - Assert.Equal(_invalidEmailString, result.Value); - } - - [Fact] - public async Task ReturnsExceptionMessageGivenInvalidInviteCode() - { - + private readonly IRepository _memberRepository = Substitute.For>(); + private readonly IRepository _invitationRepository = Substitute.For>(); + private readonly IUserRoleMembershipService _userRoleMembershipService = Substitute.For(); + private readonly IPaymentHandlerSubscription _paymentHandlerSubscription = + Substitute.For(); + private readonly IEmailService _emailService = Substitute.For(); + private readonly IMemberRegistrationService _memberRegistrationService = Substitute.For(); + private readonly IAppLogger _logger = Substitute.For>(); + private readonly MemberAddBillingActivityService _memberAddBillingActivityService = + Substitute.For(); + + private readonly INewMemberService _newMemberService; + + private readonly string _email = "TestEmail"; + private readonly string _inviteCode = "TestInviteCode"; + private readonly string _subscriptionId = "TestSubscriptionId"; + + private readonly string _validEmailAndInviteCodeString = "success"; + + private readonly string _invalidEmailString = + "Invalid email or invite code: DevBetterWeb.Core.Exceptions.InvalidEmailException"; + + private readonly string _invalidInviteCodeString = + "Invalid email or invite code: DevBetterWeb.Core.Exceptions.InvitationNotFoundException"; + + private readonly string _inactiveInviteString = + "Invalid email or invite code: DevBetterWeb.Core.Exceptions.InvitationNotActiveException"; + + public VerifyValidEmailAndInviteCode() + { + _newMemberService = new NewMemberService(_invitationRepository, + _userRoleMembershipService, + _paymentHandlerSubscription, + _emailService, + _memberRegistrationService, + _logger, + _memberAddBillingActivityService); + } + + [Fact] + public async Task ReturnsSuccessGivenValidEmailAndInviteCode() + { + var invitation = new Invitation(_email, _inviteCode, _subscriptionId); + + _invitationRepository + .FirstOrDefaultAsync(Arg.Any(), CancellationToken.None)! + .Returns(Task.FromResult(invitation)); + + var result = await _newMemberService.VerifyValidEmailAndInviteCodeAsync(_email, _inviteCode); + + await _invitationRepository.Received(1) + .FirstOrDefaultAsync(Arg.Any(), CancellationToken.None); + Assert.Equal(_validEmailAndInviteCodeString, result.Value); + } + + [Fact] + public async Task ReturnsExceptionMessageGivenInvalidEmail() + { + var invitation = new Invitation("", _inviteCode, _subscriptionId); + + _invitationRepository + .FirstOrDefaultAsync(Arg.Any(), CancellationToken.None)! + .Returns(Task.FromResult(invitation) ); + + var result = await _newMemberService.VerifyValidEmailAndInviteCodeAsync(_email, _inviteCode); + + await _invitationRepository.Received(1) + .FirstOrDefaultAsync(Arg.Any(), CancellationToken.None); + Assert.Equal(_invalidEmailString, result.Value); + } + + [Fact] + public async Task ReturnsExceptionMessageGivenInvalidInviteCode() + { #pragma warning disable CS8620 // Argument cannot be used for parameter due to differences in the nullability of reference types. #pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. - _ = _invitationRepository.Setup(r => r.FirstOrDefaultAsync(It.IsAny(), CancellationToken.None)).ReturnsAsync((Invitation)null); + _ = _invitationRepository + .FirstOrDefaultAsync(Arg.Any(), CancellationToken.None) + .Returns( Task.FromResult((Invitation)null)); #pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. #pragma warning restore CS8620 // Argument cannot be used for parameter due to differences in the nullability of reference types. - var result = await _newMemberService.VerifyValidEmailAndInviteCodeAsync(_email, _inviteCode); + var result = await _newMemberService.VerifyValidEmailAndInviteCodeAsync(_email, _inviteCode); - _invitationRepository.Verify(r => r.FirstOrDefaultAsync(It.IsAny(), CancellationToken.None), Times.Once); - Assert.Equal(_invalidInviteCodeString, result.Value); - } + await _invitationRepository.Received(1) + .FirstOrDefaultAsync(Arg.Any(), CancellationToken.None); + Assert.Equal(_invalidInviteCodeString, result.Value); + } - [Fact] - public async Task ReturnsExceptionMessageGivenInactiveInviteCode() - { - Invitation _invitation = new Invitation(_email, _inviteCode, _subscriptionId); + [Fact] + public async Task ReturnsExceptionMessageGivenInactiveInviteCode() + { + Invitation _invitation = new Invitation(_email, _inviteCode, _subscriptionId); - _invitation.Deactivate(); + _invitation.Deactivate(); - _invitationRepository.Setup(r => r.FirstOrDefaultAsync(It.IsAny(), CancellationToken.None)).ReturnsAsync(_invitation); + _invitationRepository + .FirstOrDefaultAsync(Arg.Any(), CancellationToken.None) + .Returns(Task.FromResult(_invitation)); - var result = await _newMemberService.VerifyValidEmailAndInviteCodeAsync(_email, _inviteCode); + var result = await _newMemberService.VerifyValidEmailAndInviteCodeAsync(_email, _inviteCode); - _invitationRepository.Verify(r => r.FirstOrDefaultAsync(It.IsAny(), CancellationToken.None), Times.Once); - Assert.Equal(_inactiveInviteString, result.Value); - } + await _invitationRepository.Received(1) + .FirstOrDefaultAsync(Arg.Any(), CancellationToken.None); + Assert.Equal(_inactiveInviteString, result.Value); + } } diff --git a/tests/DevBetterWeb.UnitTests/DevBetterWeb.UnitTests.csproj b/tests/DevBetterWeb.UnitTests/DevBetterWeb.UnitTests.csproj index cb14d440e..712a1e4a8 100644 --- a/tests/DevBetterWeb.UnitTests/DevBetterWeb.UnitTests.csproj +++ b/tests/DevBetterWeb.UnitTests/DevBetterWeb.UnitTests.csproj @@ -6,10 +6,8 @@ - - - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/DevBetterWeb.UnitTests/Infrastructure/Services/JsonParserServiceTests.cs b/tests/DevBetterWeb.UnitTests/Infrastructure/Services/JsonParserServiceTests.cs index f1a12afc3..34f521346 100644 --- a/tests/DevBetterWeb.UnitTests/Infrastructure/Services/JsonParserServiceTests.cs +++ b/tests/DevBetterWeb.UnitTests/Infrastructure/Services/JsonParserServiceTests.cs @@ -2,19 +2,20 @@ using DevBetterWeb.Core.Interfaces; using DevBetterWeb.Infrastructure.Services; using Microsoft.Extensions.Logging; -using Moq; using Xunit; using FluentAssertions; +using NSubstitute; +using NSubstitute.ReceivedExtensions; namespace DevBetterWeb.UnitTests.Infrastructure.Services; public class JsonParserServiceTests { private readonly IJsonParserService _jsonParserService; - private readonly Mock> _logger = new Mock>(); + private readonly ILogger _logger = Substitute.For>(); public JsonParserServiceTests() { - this._jsonParserService = new JsonParserService(this._logger.Object); + this._jsonParserService = new JsonParserService(this._logger); } [Fact] @@ -51,8 +52,9 @@ public void Parse_InvalidJson_LogsErrorMessage() Assert.NotNull(ex); } - this._logger.VerifyLog(l => l.LogError($"Failed JSON parsing for: {invlaidJson}")); - this._logger.VerifyLog(l => l.LogInformation("JSON parsing has failed")); + this._logger.Received().LogError(Arg.Any() ,$"Failed JSON parsing for: {invlaidJson}"); + // this._logger.VerifyLog(l => l.LogInformation("JSON parsing has failed")); + this._logger.Received().LogInformation("JSON parsing has failed"); } [Fact] @@ -63,6 +65,8 @@ public void Parse_ValidJson_LogsSuccessInfoMessage() var actualResult = this._jsonParserService.Parse(vlaidJson); - this._logger.VerifyLog(l => l.LogInformation("JSON parsing is successful")); + // this._logger.VerifyLog(l => l.LogInformation("JSON parsing is successful")); + this._logger.Received().LogInformation("JSON parsing is successful"); + } } diff --git a/tests/DevBetterWeb.UnitTests/Web/Services/BookServiceTests/GetAllBooksAsync.cs b/tests/DevBetterWeb.UnitTests/Web/Services/BookServiceTests/GetAllBooksAsync.cs index 3543178f9..8bd6970f8 100644 --- a/tests/DevBetterWeb.UnitTests/Web/Services/BookServiceTests/GetAllBooksAsync.cs +++ b/tests/DevBetterWeb.UnitTests/Web/Services/BookServiceTests/GetAllBooksAsync.cs @@ -1,47 +1,50 @@ using System.Collections.Generic; using System.Threading; -using Xunit; -using Moq; using System.Threading.Tasks; using DevBetterWeb.Core.Entities; -using DevBetterWeb.Web.Services; using DevBetterWeb.Core.Interfaces; using DevBetterWeb.Core.Specs; +using DevBetterWeb.Web.Services; +using NSubstitute; +using NSubstitute.ExceptionExtensions; +using Xunit; namespace DevBetterWeb.UnitTests.Web.Services.FilteredBookDetailsTests; public class GetAllBooksAsync { - private readonly Mock> _bookRepositoryMock; + private readonly IRepository _bookRepositoryMock; private readonly BookService _bookService; public GetAllBooksAsync() { - _bookRepositoryMock = new Mock>(); - _bookService = new BookService(_bookRepositoryMock.Object); + _bookRepositoryMock = Substitute.For>(); + _bookService = new BookService(_bookRepositoryMock); } [Fact] public async Task GetsAllBooks() { // Arrange - var expectedBooks = new List { - new Book { Title = "Book1", Author = "Author1" }, - new Book { Title = "Book2", Author = "Author2" } + var expectedBooks = new List + { + new Book { Title = "Book1", Author = "Author1" }, new Book { Title = "Book2", Author = "Author2" } }; - _bookRepositoryMock.Setup(repo => repo.ListAsync(It.IsAny(), CancellationToken.None)).ReturnsAsync(expectedBooks); + _bookRepositoryMock.ListAsync(Arg.Any(), Arg.Any()) + .Returns(expectedBooks); // Act var actualBooksViewModel = await _bookService.GetAllBooksAsync(); // Assert - _bookRepositoryMock.Verify(repo => repo.ListAsync(It.IsAny(), CancellationToken.None), Times.Once); + await _bookRepositoryMock.Received(1).ListAsync(Arg.Any(), Arg.Any()); Assert.Equal(expectedBooks.Count, actualBooksViewModel.Count); foreach (var expectedBook in expectedBooks) { - Assert.Contains(actualBooksViewModel, bvm => bvm.Title == expectedBook.Title && bvm.Author == expectedBook.Author); + Assert.Contains(actualBooksViewModel, + bvm => bvm.Title == expectedBook.Title && bvm.Author == expectedBook.Author); } } @@ -49,13 +52,14 @@ public async Task GetsAllBooks() public async Task ReturnsEmptyListGivenNoBooks() { // Arrange - _bookRepositoryMock.Setup(repo => repo.ListAsync(It.IsAny(), CancellationToken.None)).ReturnsAsync(new List()); + _bookRepositoryMock.ListAsync(Arg.Any(), Arg.Any()) + .Returns(new List()); // Act var actualBooksViewModel = await _bookService.GetAllBooksAsync(); // Assert - _bookRepositoryMock.Verify(repo => repo.ListAsync(It.IsAny(), CancellationToken.None), Times.Once); + await _bookRepositoryMock.Received(1).ListAsync(Arg.Any(), Arg.Any()); Assert.Empty(actualBooksViewModel); } @@ -66,44 +70,29 @@ public async Task ReturnsBooksInCorrectOrder() // Arrange var book1 = new Book { - Title = "Book1", - Author = "Author1", - MembersWhoHaveRead = new List - { - new Member(), - }, - BookCategoryId = 1 + Title = "Book1", Author = "Author1", MembersWhoHaveRead = new List { new Member(), }, BookCategoryId = 1 }; var book2 = new Book { Title = "Book2", Author = "Author2", - MembersWhoHaveRead = new List - { - new Member(), - new Member(), - }, + MembersWhoHaveRead = new List { new Member(), new Member(), }, BookCategoryId = 1 }; var book3 = new Book { - Title = "Book3", - Author = "Author3", - MembersWhoHaveRead = new List - { - new Member(), - }, - BookCategoryId = 2 + Title = "Book3", Author = "Author3", MembersWhoHaveRead = new List { new Member(), }, BookCategoryId = 2 }; var expectedBooks = new List { book1, book2, book3 }; - _bookRepositoryMock.Setup(repo => repo.ListAsync(It.IsAny(), CancellationToken.None)).ReturnsAsync(expectedBooks); + _bookRepositoryMock.ListAsync(Arg.Any(), Arg.Any()) + .Returns(expectedBooks); // Act var actualBooksViewModel = await _bookService.GetAllBooksAsync(); // Assert - _bookRepositoryMock.Verify(repo => repo.ListAsync(It.IsAny(), CancellationToken.None), Times.Once); + await _bookRepositoryMock.Received(1).ListAsync(Arg.Any(), Arg.Any()); Assert.Equal(expectedBooks.Count, actualBooksViewModel.Count); Assert.Equal(book2.Title, actualBooksViewModel[0].Title); // Book2 has higher ReadsCount @@ -115,7 +104,8 @@ public async Task ReturnsBooksInCorrectOrder() public async Task ThrowsExceptionWhenRepositoryFails() { // Arrange - _bookRepositoryMock.Setup(repo => repo.ListAsync(It.IsAny(), CancellationToken.None)).ThrowsAsync(new System.Exception()); + _bookRepositoryMock.ListAsync(Arg.Any(), Arg.Any()) + .Throws(new System.Exception()); // Act & Assert await Assert.ThrowsAsync(() => _bookService.GetAllBooksAsync()); diff --git a/tests/DevBetterWeb.UnitTests/Web/Services/FilteredBookDetailsTests/GetBookDetailsAsync.cs b/tests/DevBetterWeb.UnitTests/Web/Services/FilteredBookDetailsTests/GetBookDetailsAsync.cs index 0c18f1ec9..4f1f7e991 100644 --- a/tests/DevBetterWeb.UnitTests/Web/Services/FilteredBookDetailsTests/GetBookDetailsAsync.cs +++ b/tests/DevBetterWeb.UnitTests/Web/Services/FilteredBookDetailsTests/GetBookDetailsAsync.cs @@ -2,7 +2,7 @@ using System.Threading; using DevBetterWeb.Web.Interfaces; using Xunit; -using Moq; +using NSubstitute; using System.Threading.Tasks; using DevBetterWeb.Core.Entities; using DevBetterWeb.Infrastructure.Interfaces; @@ -13,15 +13,15 @@ namespace DevBetterWeb.UnitTests.Web.Services.FilteredBookDetailsTests; public class GetBookDetailsAsync { - private readonly Mock _nonCurrentMembersServiceMock; - private readonly Mock _bookServiceMock; + private readonly INonCurrentMembersService _nonCurrentMembersServiceMock; + private readonly IBookService _bookServiceMock; private readonly FilteredBookDetailsService _filteredBookDetailsService; public GetBookDetailsAsync() { - _nonCurrentMembersServiceMock = new Mock(); - _bookServiceMock = new Mock(); - _filteredBookDetailsService = new FilteredBookDetailsService(_nonCurrentMembersServiceMock.Object, _bookServiceMock.Object); + _nonCurrentMembersServiceMock = Substitute.For(); + _bookServiceMock = Substitute.For(); + _filteredBookDetailsService = new FilteredBookDetailsService(_nonCurrentMembersServiceMock, _bookServiceMock); } [Fact] @@ -29,7 +29,7 @@ public async Task ReturnsNullGivenNonExistentBookId() { // Arrange var bookId = "1"; - _bookServiceMock.Setup(s => s.GetBookByIdAsync(int.Parse(bookId))).ReturnsAsync((BookDetailsViewModel?)null); + _bookServiceMock.GetBookByIdAsync(int.Parse(bookId)).Returns((BookDetailsViewModel?)null); // Act var result = await _filteredBookDetailsService.GetBookDetailsAsync(bookId); @@ -44,7 +44,7 @@ public async Task ReturnBookDetailsGivenValidBookId() // Arrange var bookId = "1"; var bookDetails = new BookDetailsViewModel(); - _bookServiceMock.Setup(s => s.GetBookByIdAsync(int.Parse(bookId))).ReturnsAsync(bookDetails); + _bookServiceMock.GetBookByIdAsync(int.Parse(bookId)).Returns(bookDetails); // Act var result = await _filteredBookDetailsService.GetBookDetailsAsync(bookId); @@ -67,9 +67,10 @@ public async Task FilterNonCurrentMembersGivenValidBookId() { MembersWhoHaveRead = new List { new Member { Id = 1 } } }; - _bookServiceMock.Setup(s => s.GetBookByIdAsync(int.Parse(bookId))).ReturnsAsync(bookDetails); - _nonCurrentMembersServiceMock.Setup(s => s.GetUsersIdsWithoutRolesAsync()).ReturnsAsync(new List { "2", "3" }); - _nonCurrentMembersServiceMock.Setup(s => s.GetNonCurrentMembersAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(new List { 2, 3 }); + _bookServiceMock.GetBookByIdAsync(int.Parse(bookId)).Returns(bookDetails); + _nonCurrentMembersServiceMock.GetUsersIdsWithoutRolesAsync().Returns(new List { "2", "3" }); + _nonCurrentMembersServiceMock.GetNonCurrentMembersAsync(Arg.Any>(), Arg.Any()) + .Returns(new List { 2, 3 }); // Act var result = await _filteredBookDetailsService.GetBookDetailsAsync(bookId); @@ -78,5 +79,4 @@ public async Task FilterNonCurrentMembersGivenValidBookId() Assert.NotNull(result); Assert.Equal(filteredBookDetails.MembersWhoHaveRead.Count, result.MembersWhoHaveRead.Count); } - } diff --git a/tests/DevBetterWeb.UnitTests/Web/Services/FilteredBookDetailsTests/RemoveNonCurrentMembersFromBookDetailsAsync.cs b/tests/DevBetterWeb.UnitTests/Web/Services/FilteredBookDetailsTests/RemoveNonCurrentMembersFromBookDetailsAsync.cs index e52571e01..67c80d194 100644 --- a/tests/DevBetterWeb.UnitTests/Web/Services/FilteredBookDetailsTests/RemoveNonCurrentMembersFromBookDetailsAsync.cs +++ b/tests/DevBetterWeb.UnitTests/Web/Services/FilteredBookDetailsTests/RemoveNonCurrentMembersFromBookDetailsAsync.cs @@ -7,21 +7,21 @@ using DevBetterWeb.Web.Interfaces; using DevBetterWeb.Web.Pages.Leaderboard; using DevBetterWeb.Web.Services; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.UnitTests.Web.Services.FilteredBookDetailsTests; public class RemoveNonCurrentMembersFromBookDetailsAsync { - private readonly Mock _mockNonCurrentMembersService; + private readonly INonCurrentMembersService _mockNonCurrentMembersService; private readonly FilteredBookDetailsService _filteredBookDetailsService; public RemoveNonCurrentMembersFromBookDetailsAsync() { - _mockNonCurrentMembersService = new Mock(); - var bookService = new Mock(); - _filteredBookDetailsService = new FilteredBookDetailsService(_mockNonCurrentMembersService.Object, bookService.Object); + _mockNonCurrentMembersService = Substitute.For(); + var bookService = Substitute.For(); + _filteredBookDetailsService = new FilteredBookDetailsService(_mockNonCurrentMembersService, bookService); } [Fact] @@ -32,11 +32,11 @@ public async Task RemoveNonCurrentMembersGivenNonCurrentMembersInBookDetailsView { MembersWhoHaveRead = new List { new Member { Id = 1 }, new Member { Id = 2 }, new Member { Id = 3 } } }; - _mockNonCurrentMembersService.Setup(s => s.GetUsersIdsWithoutRolesAsync()) - .ReturnsAsync(new List { "1", "2" }); + _mockNonCurrentMembersService.GetUsersIdsWithoutRolesAsync() + .Returns(new List { "1", "2" }); _mockNonCurrentMembersService - .Setup(s => s.GetNonCurrentMembersAsync(It.IsAny>(), It.IsAny())) - .ReturnsAsync(new List { 1, 2 }); + .GetNonCurrentMembersAsync(Arg.Any>(), Arg.Any()) + .Returns(new List { 1, 2 }); // Act var result = await _filteredBookDetailsService.RemoveNonCurrentMembersFromBookDetailsAsync(bookDetailsViewModel); @@ -54,11 +54,11 @@ public async Task NotRemoveCurrentMembersGivenCurrentMembersInBookDetailsViewMod { MembersWhoHaveRead = new List { new Member { Id = 1 }, new Member { Id = 2 }, new Member { Id = 3 } } }; - _mockNonCurrentMembersService.Setup(s => s.GetUsersIdsWithoutRolesAsync()) - .ReturnsAsync(new List { "4", "5" }); + _mockNonCurrentMembersService.GetUsersIdsWithoutRolesAsync() + .Returns(new List { "4", "5" }); _mockNonCurrentMembersService - .Setup(s => s.GetNonCurrentMembersAsync(It.IsAny>(), It.IsAny())) - .ReturnsAsync(new List { 4, 5 }); + .GetNonCurrentMembersAsync(Arg.Any>(), Arg.Any()) + .Returns(new List { 4, 5 }); // Act var result = await _filteredBookDetailsService.RemoveNonCurrentMembersFromBookDetailsAsync(bookDetailsViewModel); @@ -75,10 +75,10 @@ public async Task ReturnSameBookDetailsGivenNoNonCurrentMembersInBookDetailsView { MembersWhoHaveRead = new List { new Member { Id = 1 }, new Member { Id = 2 }, new Member { Id = 3 } } }; - _mockNonCurrentMembersService.Setup(s => s.GetUsersIdsWithoutRolesAsync()).ReturnsAsync(new List { }); + _mockNonCurrentMembersService.GetUsersIdsWithoutRolesAsync().Returns(new List { }); _mockNonCurrentMembersService - .Setup(s => s.GetNonCurrentMembersAsync(It.IsAny>(), It.IsAny())) - .ReturnsAsync(new List { }); + .GetNonCurrentMembersAsync(Arg.Any>(), Arg.Any()) + .Returns(new List { }); // Act var result = await _filteredBookDetailsService.RemoveNonCurrentMembersFromBookDetailsAsync(bookDetailsViewModel); @@ -92,8 +92,11 @@ public async Task HandleEmptyMembersListGivenBookDetailsViewModelWithNoMembers() { // Arrange var bookDetailsViewModel = new BookDetailsViewModel { MembersWhoHaveRead = new List { } }; - _mockNonCurrentMembersService.Setup(s => s.GetUsersIdsWithoutRolesAsync()).ReturnsAsync(new List { "1", "2" }); - _mockNonCurrentMembersService.Setup(s => s.GetNonCurrentMembersAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(new List { 1, 2 }); + _mockNonCurrentMembersService.GetUsersIdsWithoutRolesAsync() + .Returns(new List { "1", "2" }); + _mockNonCurrentMembersService + .GetNonCurrentMembersAsync(Arg.Any>(), Arg.Any()) + .Returns(new List { 1, 2 }); // Act var result = await _filteredBookDetailsService.RemoveNonCurrentMembersFromBookDetailsAsync(bookDetailsViewModel); @@ -110,8 +113,11 @@ public async Task RemoveAllMembersGivenAllNonCurrentMembersInBookDetailsViewMode { MembersWhoHaveRead = new List { new Member { Id = 1 }, new Member { Id = 2 }, new Member { Id = 3 } } }; - _mockNonCurrentMembersService.Setup(s => s.GetUsersIdsWithoutRolesAsync()).ReturnsAsync(new List { "1", "2", "3" }); - _mockNonCurrentMembersService.Setup(s => s.GetNonCurrentMembersAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(new List { 1, 2, 3 }); + _mockNonCurrentMembersService.GetUsersIdsWithoutRolesAsync() + .Returns(new List { "1", "2", "3" }); + _mockNonCurrentMembersService + .GetNonCurrentMembersAsync(Arg.Any>(), Arg.Any()) + .Returns(new List { 1, 2, 3 }); // Act var result = await _filteredBookDetailsService.RemoveNonCurrentMembersFromBookDetailsAsync(bookDetailsViewModel); @@ -120,4 +126,3 @@ public async Task RemoveAllMembersGivenAllNonCurrentMembersInBookDetailsViewMode Assert.Empty(result.MembersWhoHaveRead); } } - diff --git a/tests/DevBetterWeb.UnitTests/Web/Services/FilteredLeaderboardTests/RemoveNonCurrentMembersFromLeaderBoardAsync.cs b/tests/DevBetterWeb.UnitTests/Web/Services/FilteredLeaderboardTests/RemoveNonCurrentMembersFromLeaderBoardAsync.cs index b7d2528f0..460cce071 100644 --- a/tests/DevBetterWeb.UnitTests/Web/Services/FilteredLeaderboardTests/RemoveNonCurrentMembersFromLeaderBoardAsync.cs +++ b/tests/DevBetterWeb.UnitTests/Web/Services/FilteredLeaderboardTests/RemoveNonCurrentMembersFromLeaderBoardAsync.cs @@ -6,20 +6,20 @@ using DevBetterWeb.Web.Interfaces; using DevBetterWeb.Web.Models; using DevBetterWeb.Web.Services; -using Moq; +using NSubstitute; using Xunit; namespace DevBetterWeb.UnitTests.Web.Services.FilteredLeaderboardTests; public class FilteredLeaderboardServiceTests { - private readonly Mock _nonCurrentMembersServiceMock; - private readonly Mock _memberServiceMock; + private readonly INonCurrentMembersService _nonCurrentMembersServiceMock; + private readonly IMemberService _memberServiceMock; public FilteredLeaderboardServiceTests() { - _nonCurrentMembersServiceMock = new Mock(); - _memberServiceMock = new Mock(); + _nonCurrentMembersServiceMock = Substitute.For(); + _memberServiceMock = Substitute.For(); } [Fact] @@ -30,15 +30,15 @@ public async Task RemovesNonCurrentMembersGivenBookCategories() List nonUsersId = new List { "3" }; List nonMembersId = new List { 3 }; - _nonCurrentMembersServiceMock.Setup(service => service.GetUsersIdsWithoutRolesAsync()) - .ReturnsAsync(nonUsersId); - _nonCurrentMembersServiceMock.Setup(service => service.GetNonCurrentMembersAsync(nonUsersId, CancellationToken.None)) - .ReturnsAsync(nonMembersId); + _nonCurrentMembersServiceMock.GetUsersIdsWithoutRolesAsync() + .Returns(nonUsersId); + _nonCurrentMembersServiceMock.GetNonCurrentMembersAsync(nonUsersId, CancellationToken.None) + .Returns(nonMembersId); - _memberServiceMock.Setup(service => service.GetActiveAlumniMembersAsync()) - .ReturnsAsync(new List()); + _memberServiceMock.GetActiveAlumniMembersAsync() + .Returns(new List()); - var service = new FilteredLeaderboardService(_nonCurrentMembersServiceMock.Object, _memberServiceMock.Object); + var service = new FilteredLeaderboardService(_nonCurrentMembersServiceMock, _memberServiceMock); // Act var filteredBookCategories = await service.RemoveNonCurrentMembersFromLeaderBoardAsync(bookCategories); @@ -57,34 +57,34 @@ public async Task RemovesNonCurrentMembersGivenBookCategories() private List CreateSampleBookCategories() { return new List + { + new() + { + Id = 1, + Title = "Category 1", + Members = new List + { + new() { Id = 1, FullName = "Member 1", BooksReadCountByCategory = 1 }, + new() { Id = 2, FullName = "Member 2", BooksReadCountByCategory = 1 }, + new() { Id = 3, FullName = "Non-Member", BooksReadCountByCategory = 1 } + }, + Books = new List + { + new BookDto { - new() - { - Id = 1, - Title = "Category 1", - Members = new List - { - new() { Id = 1, FullName = "Member 1", BooksReadCountByCategory = 1 }, - new() { Id = 2, FullName = "Member 2", BooksReadCountByCategory = 1 }, - new() { Id = 3, FullName = "Non-Member", BooksReadCountByCategory = 1 } - }, - Books = new List - { - new BookDto - { - Id = 1, - Title = "Book 1", - Author = "Author 1", - MembersWhoHaveReadCount = 3, - MembersWhoHaveRead = new List - { - new() { Id = 1, FullName = "Member 1" }, - new() { Id = 2, FullName = "Member 2" }, - new() { Id = 3, FullName = "Non-Member" } - } - } - } - } - }; + Id = 1, + Title = "Book 1", + Author = "Author 1", + MembersWhoHaveReadCount = 3, + MembersWhoHaveRead = new List + { + new() { Id = 1, FullName = "Member 1" }, + new() { Id = 2, FullName = "Member 2" }, + new() { Id = 3, FullName = "Non-Member" } + } + } + } + } + }; } } diff --git a/tests/DevBetterWeb.UnitTests/Web/Services/LeaderboardServiceTests/SetBookCategoriesAsync.cs b/tests/DevBetterWeb.UnitTests/Web/Services/LeaderboardServiceTests/SetBookCategoriesAsync.cs index dcea8d5e8..4bf4b3cd0 100644 --- a/tests/DevBetterWeb.UnitTests/Web/Services/LeaderboardServiceTests/SetBookCategoriesAsync.cs +++ b/tests/DevBetterWeb.UnitTests/Web/Services/LeaderboardServiceTests/SetBookCategoriesAsync.cs @@ -3,194 +3,194 @@ using DevBetterWeb.Web.Models; using DevBetterWeb.Web.Services; using Xunit; -using Moq; +using NSubstitute; using System.Threading; using System.Threading.Tasks; using System; using System.Linq; +using NSubstitute.ExceptionExtensions; namespace DevBetterWeb.UnitTests.Web.Services.LeaderboardServiceTests; -public class SetBookCategoriesAsync -{ - private readonly Mock _rankAndOrderServiceMock; - private readonly Mock _bookCategoryServiceMock; - private readonly Mock _filteredLeaderboardServiceMock; - private readonly LeaderboardService _leaderboardService; - - public SetBookCategoriesAsync() - { - _rankAndOrderServiceMock = new Mock(); - _bookCategoryServiceMock = new Mock(); - _filteredLeaderboardServiceMock = new Mock(); - _leaderboardService = new LeaderboardService(_rankAndOrderServiceMock.Object, _bookCategoryServiceMock.Object, _filteredLeaderboardServiceMock.Object); - } - - [Fact] - public async Task UpdateRanksAndOrdersGivenBookCategories() - { - // Arrange - var bookCategories = new List - { - new BookCategoryDto - { - Members = new List - { - new MemberForBookDto { Id = 1, UserId = "UserId1" }, - new MemberForBookDto { Id = 2, UserId = "UserId2" } - } - } - }; - - _bookCategoryServiceMock.Setup(bs => bs.GetBookCategoriesAsync()).ReturnsAsync(bookCategories); - _filteredLeaderboardServiceMock.Setup(fs => fs.RemoveNonCurrentMembersFromLeaderBoardAsync(bookCategories, CancellationToken.None)).ReturnsAsync(bookCategories); - - // Act - await _leaderboardService.SetBookCategoriesAsync(); - - // Assert - _rankAndOrderServiceMock.Verify(rs => rs.UpdateRanksAndReadBooksCountForMemberAsync(It.IsAny>()), Times.Never); - _rankAndOrderServiceMock.Verify(rs => rs.UpdateMembersReadRank(It.IsAny>()), Times.Once); - _rankAndOrderServiceMock.Verify(rs => rs.UpdateBooksRank(It.IsAny>()), Times.Once); - _rankAndOrderServiceMock.Verify(rs => rs.OrderByRankForMembersAndBooks(It.IsAny>()), Times.Once); - } - - [Fact] - public async Task NotIncludeNonActiveMemberInRankGivenNonActiveMember() - { - // Arrange - var bookCategories = new List - { - new BookCategoryDto - { - Members = new List - { - new MemberForBookDto { Id = 1, UserId = "UserId1" }, - new MemberForBookDto { Id = 2, UserId = "UserId2" } - } - } - }; - var bookCategoriesWithoutNonActiveMember = new List - { - new BookCategoryDto - { - Members = new List - { - new MemberForBookDto { Id = 2, UserId = "UserId2" } - } - } - }; - - _bookCategoryServiceMock.Setup(bs => bs.GetBookCategoriesAsync()).ReturnsAsync(bookCategories); - _filteredLeaderboardServiceMock.Setup(fs => fs.RemoveNonCurrentMembersFromLeaderBoardAsync(bookCategories, CancellationToken.None)).ReturnsAsync(bookCategoriesWithoutNonActiveMember); - - // Act - var result = await _leaderboardService.SetBookCategoriesAsync(); - - // Assert - Assert.Single(result[0].Members); - Assert.Equal(2, result[0].Members[0].Id); - } - - [Fact] - public async Task ReturnsEmptyListGivenNoBookCategories() - { - // Arrange - var bookCategories = new List(); - - _bookCategoryServiceMock.Setup(bs => bs.GetBookCategoriesAsync()).ReturnsAsync(bookCategories); - _filteredLeaderboardServiceMock.Setup(fs => fs.RemoveNonCurrentMembersFromLeaderBoardAsync(bookCategories, CancellationToken.None)).ReturnsAsync(bookCategories); - - // Act - var result = await _leaderboardService.SetBookCategoriesAsync(); - - // Assert - Assert.Empty(result); - } - - [Fact] - public async Task ThrowsExceptionGivenGetBookCategoriesAsyncFails() - { - // Arrange - _bookCategoryServiceMock.Setup(bs => bs.GetBookCategoriesAsync()).ThrowsAsync(new ArgumentNullException()); - - // Act & Assert - await Assert.ThrowsAsync(() => _leaderboardService.SetBookCategoriesAsync()); - } - - [Fact] - public async Task OrdersMemberRanksCorrectlyGivenUnorderedRanks() - { - // Arrange - var bookCategories = new List - { - new BookCategoryDto - { - Members = new List - { - new MemberForBookDto { Id = 1, UserId = "UserId1", BooksRank = 2}, - new MemberForBookDto { Id = 2, UserId = "UserId2", BooksRank = 1 } - } - } - }; - - _bookCategoryServiceMock.Setup(bs => bs.GetBookCategoriesAsync()).ReturnsAsync(bookCategories); - _filteredLeaderboardServiceMock.Setup(fs => fs.RemoveNonCurrentMembersFromLeaderBoardAsync(bookCategories, CancellationToken.None)).ReturnsAsync(bookCategories); - - _rankAndOrderServiceMock.Setup(rs => rs.OrderByRankForMembersAndBooks(It.IsAny>())) - .Callback((List categories) => - { - foreach (var category in categories) - { - category.Members = category.Members.OrderBy(m => m.BooksRank).ToList(); - } - }); - - // Act - var result = await _leaderboardService.SetBookCategoriesAsync(); - - // Assert - Assert.Equal(2, result[0].Members.Count); - Assert.Equal(1, result[0].Members[0].BooksRank); - Assert.Equal(2, result[0].Members[1].BooksRank); - } - - [Fact] - public async Task OrdersMembersCorrectlyByBooksReadCountGivenUnorderedMembers() - { - // Arrange - var bookCategories = new List - { - new BookCategoryDto - { - Members = new List - { - new MemberForBookDto { Id = 1, UserId = "UserId1", BooksReadCount = 1, BooksRank = 2 }, - new MemberForBookDto { Id = 2, UserId = "UserId2", BooksReadCount = 3, BooksRank = 1 } - } - } - }; - - _bookCategoryServiceMock.Setup(bs => bs.GetBookCategoriesAsync()).ReturnsAsync(bookCategories); - _filteredLeaderboardServiceMock.Setup(fs => fs.RemoveNonCurrentMembersFromLeaderBoardAsync(bookCategories, CancellationToken.None)).ReturnsAsync(bookCategories); - - _rankAndOrderServiceMock.Setup(rs => rs.OrderByRankForMembersAndBooks(It.IsAny>())) - .Callback((List categories) => - { - foreach (var category in categories) - { - category.Members = category.Members.OrderByDescending(m => m.BooksReadCount).ThenBy(m => m.BooksRank).ToList(); - } - }); - - // Act - var result = await _leaderboardService.SetBookCategoriesAsync(); - - // Assert - Assert.Equal(2, result[0].Members.Count); - Assert.Equal(3, result[0].Members[0].BooksReadCount); - Assert.Equal(1, result[0].Members[0].BooksRank); - Assert.Equal(1, result[0].Members[1].BooksReadCount); - Assert.Equal(2, result[0].Members[1].BooksRank); - } -} + public class SetBookCategoriesAsync + { + private readonly IRankAndOrderService _rankAndOrderServiceMock; + private readonly IBookCategoryService _bookCategoryServiceMock; + private readonly IFilteredLeaderboardService _filteredLeaderboardServiceMock; + private readonly LeaderboardService _leaderboardService; + + public SetBookCategoriesAsync() + { + _rankAndOrderServiceMock = Substitute.For(); + _bookCategoryServiceMock = Substitute.For(); + _filteredLeaderboardServiceMock = Substitute.For(); + _leaderboardService = new LeaderboardService(_rankAndOrderServiceMock, _bookCategoryServiceMock, _filteredLeaderboardServiceMock); + } + + [Fact] + public async Task UpdateRanksAndOrdersGivenBookCategories() + { + // Arrange + var bookCategories = new List + { + new BookCategoryDto + { + Members = new List + { + new MemberForBookDto { Id = 1, UserId = "UserId1" }, + new MemberForBookDto { Id = 2, UserId = "UserId2" } + } + } + }; + + _bookCategoryServiceMock.GetBookCategoriesAsync().Returns(bookCategories); + _filteredLeaderboardServiceMock.RemoveNonCurrentMembersFromLeaderBoardAsync(bookCategories, CancellationToken.None).Returns(bookCategories); + + // Act + await _leaderboardService.SetBookCategoriesAsync(); + + // Assert + _rankAndOrderServiceMock.Received(1).UpdateMembersReadRank(Arg.Any>()); + _rankAndOrderServiceMock.Received(1).UpdateBooksRank(Arg.Any>()); + _rankAndOrderServiceMock.Received(1).OrderByRankForMembersAndBooks(Arg.Any>()); + await _rankAndOrderServiceMock.DidNotReceiveWithAnyArgs().UpdateRanksAndReadBooksCountForMemberAsync(Arg.Any>()); + } + + [Fact] + public async Task NotIncludeNonActiveMemberInRankGivenNonActiveMember() + { + // Arrange + var bookCategories = new List + { + new BookCategoryDto + { + Members = new List + { + new MemberForBookDto { Id = 1, UserId = "UserId1" }, + new MemberForBookDto { Id = 2, UserId = "UserId2" } + } + } + }; + var bookCategoriesWithoutNonActiveMember = new List + { + new BookCategoryDto + { + Members = new List + { + new MemberForBookDto { Id = 2, UserId = "UserId2" } + } + } + }; + + _bookCategoryServiceMock.GetBookCategoriesAsync().Returns(bookCategories); + _filteredLeaderboardServiceMock.RemoveNonCurrentMembersFromLeaderBoardAsync(bookCategories, CancellationToken.None).Returns(bookCategoriesWithoutNonActiveMember); + + // Act + var result = await _leaderboardService.SetBookCategoriesAsync(); + + // Assert + Assert.Single(result[0].Members); + Assert.Equal(2, result[0].Members[0].Id); + } + + [Fact] + public async Task ReturnsEmptyListGivenNoBookCategories() + { + // Arrange + var bookCategories = new List(); + + _bookCategoryServiceMock.GetBookCategoriesAsync().Returns(bookCategories); + _filteredLeaderboardServiceMock.RemoveNonCurrentMembersFromLeaderBoardAsync(bookCategories, CancellationToken.None).Returns(bookCategories); + + // Act + var result = await _leaderboardService.SetBookCategoriesAsync(); + + // Assert + Assert.Empty(result); + } + + [Fact] + public async Task ThrowsExceptionGivenGetBookCategoriesAsyncFails() + { + // Arrange + _bookCategoryServiceMock.GetBookCategoriesAsync().Throws(new ArgumentNullException()); + + // Act & Assert + await Assert.ThrowsAsync(() => _leaderboardService.SetBookCategoriesAsync()); + } + + [Fact] + public async Task OrdersMemberRanksCorrectlyGivenUnorderedRanks() + { + // Arrange + var bookCategories = new List + { + new BookCategoryDto + { + Members = new List + { + new MemberForBookDto { Id = 1, UserId = "UserId1", BooksRank = 2}, + new MemberForBookDto { Id = 2, UserId = "UserId2", BooksRank = 1 } + } + } + }; + + _bookCategoryServiceMock.GetBookCategoriesAsync().Returns(bookCategories); + _filteredLeaderboardServiceMock.RemoveNonCurrentMembersFromLeaderBoardAsync(bookCategories, CancellationToken.None).Returns(bookCategories); + + _rankAndOrderServiceMock.OrderByRankForMembersAndBooks(Arg.Do>(categories => + { + foreach (var category in categories) + { + category.Members = category.Members.OrderBy(m => m.BooksRank).ToList(); + } + })); + + // Act + var result = await _leaderboardService.SetBookCategoriesAsync(); + + // Assert + Assert.Equal(2, result[0].Members.Count); + Assert.Equal(1, result[0].Members[0].BooksRank); + Assert.Equal(2, result[0].Members[1].BooksRank); + } + + [Fact] + public async Task OrdersMembersCorrectlyByBooksReadCountGivenUnorderedMembers() + { + // Arrange + var bookCategories = new List + { + new BookCategoryDto + { + Members = new List + { + new MemberForBookDto { Id = 1, UserId = "UserId1", BooksReadCount = 1, BooksRank = 2 }, + new MemberForBookDto { Id = 2, UserId = "UserId2", BooksReadCount = 3, BooksRank = 1 } + } + } + }; + + _bookCategoryServiceMock.GetBookCategoriesAsync().Returns(bookCategories); + _filteredLeaderboardServiceMock.RemoveNonCurrentMembersFromLeaderBoardAsync(bookCategories, CancellationToken.None).Returns(bookCategories); + + _rankAndOrderServiceMock.OrderByRankForMembersAndBooks(Arg.Do>(categories => + { + foreach (var category in categories) + { + category.Members = category.Members.OrderByDescending(m => m.BooksReadCount).ThenBy(m => m.BooksRank).ToList(); + } + })); + + // Act + var result = await _leaderboardService.SetBookCategoriesAsync(); + + // Assert + Assert.Equal(2, result[0].Members.Count); + Assert.Equal(3, result[0].Members[0].BooksReadCount); + Assert.Equal(1, result[0].Members[0].BooksRank); + Assert.Equal(1, result[0].Members[1].BooksReadCount); + Assert.Equal(2, result[0].Members[1].BooksRank); + } + } + diff --git a/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/OrderByRankForMembersAndBooks.cs b/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/OrderByRankForMembersAndBooks.cs index 03b62c4d3..d81e67fc8 100644 --- a/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/OrderByRankForMembersAndBooks.cs +++ b/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/OrderByRankForMembersAndBooks.cs @@ -4,45 +4,54 @@ using DevBetterWeb.Web.Models; using DevBetterWeb.Web.Services; using Xunit; -using Moq; +using NSubstitute; using System; namespace DevBetterWeb.UnitTests.Web.Services.RankAndOrderServiceTests; public class OrderByRankForMembersAndBooks { - private readonly Mock _mockRankingService; + private readonly IRankingService _mockRankingService; private readonly RankAndOrderService _rankAndOrderService; public OrderByRankForMembersAndBooks() { - _mockRankingService = new Mock(); - var mockMemberService = new Mock(); - _rankAndOrderService = new RankAndOrderService(_mockRankingService.Object, mockMemberService.Object); + _mockRankingService = Substitute.For(); + var mockMemberService = Substitute.For(); + _rankAndOrderService = new RankAndOrderService(_mockRankingService, mockMemberService); } private List GetTestBookCategories() { return new List + { + new BookCategoryDto + { + Id = 1, + Books = new List { - new BookCategoryDto + new BookDto + { + Id = 1, + MembersWhoHaveRead = new List { - Id = 1, - Books = new List - { - new BookDto - { - Id = 1, - MembersWhoHaveRead = new List - { - new MemberForBookDto { Id = 1, RoleName = AuthConstants.Roles.ALUMNI, UserId = "1", FullName = "Alumni1" }, - new MemberForBookDto { Id = 2, RoleName = AuthConstants.Roles.MEMBERS, UserId = "2", FullName = "Member1" }, - new MemberForBookDto { Id = 3, RoleName = AuthConstants.Roles.ALUMNI, UserId = "3", FullName = "Alumni2" } - } - } - } + new MemberForBookDto + { + Id = 1, RoleName = AuthConstants.Roles.ALUMNI, UserId = "1", FullName = "Alumni1" + }, + new MemberForBookDto + { + Id = 2, RoleName = AuthConstants.Roles.MEMBERS, UserId = "2", FullName = "Member1" + }, + new MemberForBookDto + { + Id = 3, RoleName = AuthConstants.Roles.ALUMNI, UserId = "3", FullName = "Alumni2" + } } - }; + } + } + } + }; } [Fact] @@ -55,8 +64,8 @@ public void OrderMembersAndBooksGivenBookCategories() _rankAndOrderService.OrderByRankForMembersAndBooks(bookCategories); // Assert - _mockRankingService.Verify(rs => rs.OrderMembersByRank(It.IsAny>()), Times.Exactly(bookCategories.Count * 2)); - _mockRankingService.Verify(rs => rs.OrderBooksByRank(It.IsAny>()), Times.Exactly(bookCategories.Count)); + _mockRankingService.Received(bookCategories.Count * 2).OrderMembersByRank(Arg.Any>()); + _mockRankingService.Received(bookCategories.Count).OrderBooksByRank(Arg.Any>()); } [Fact] @@ -69,8 +78,8 @@ public void NotCallRankingServiceMethodsGivenEmptyList() _rankAndOrderService.OrderByRankForMembersAndBooks(bookCategories); // Assert - _mockRankingService.Verify(rs => rs.OrderMembersByRank(It.IsAny>()), Times.Never()); - _mockRankingService.Verify(rs => rs.OrderBooksByRank(It.IsAny>()), Times.Never()); + _mockRankingService.DidNotReceive().OrderMembersByRank(Arg.Any>()); + _mockRankingService.DidNotReceive().OrderBooksByRank(Arg.Any>()); } [Fact] @@ -92,5 +101,4 @@ public void ThrowsArgumentExceptionGivenListContainsNull() // Act & Assert Assert.Throws(() => _rankAndOrderService.OrderByRankForMembersAndBooks(bookCategories)); } - } diff --git a/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/UpdateBooksRank.cs b/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/UpdateBooksRank.cs index bfd3db785..676193649 100644 --- a/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/UpdateBooksRank.cs +++ b/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/UpdateBooksRank.cs @@ -5,45 +5,53 @@ using DevBetterWeb.Web.Models; using DevBetterWeb.Web.Services; using Xunit; -using Moq; -using System.Linq; +using NSubstitute; namespace DevBetterWeb.UnitTests.Web.Services.RankAndOrderServiceTests; public class UpdateBooksRank { - private readonly Mock _mockRankingService; + private readonly IRankingService _mockRankingService; private readonly RankAndOrderService _rankAndOrderService; public UpdateBooksRank() { - _mockRankingService = new Mock(); - var mockMemberService = new Mock(); - _rankAndOrderService = new RankAndOrderService(_mockRankingService.Object, mockMemberService.Object); + _mockRankingService = Substitute.For(); + var mockMemberService = Substitute.For(); + _rankAndOrderService = new RankAndOrderService(_mockRankingService, mockMemberService); } private List GetTestBookCategories() { return new List + { + new BookCategoryDto + { + Id = 1, + Books = new List { - new BookCategoryDto + new BookDto + { + Id = 1, + MembersWhoHaveRead = new List { - Id = 1, - Books = new List - { - new BookDto - { - Id = 1, - MembersWhoHaveRead = new List - { - new MemberForBookDto { Id = 1, RoleName = AuthConstants.Roles.ALUMNI, UserId = "1", FullName = "Alumni1" }, - new MemberForBookDto { Id = 2, RoleName = AuthConstants.Roles.MEMBERS, UserId = "2", FullName = "Member1" }, - new MemberForBookDto { Id = 3, RoleName = AuthConstants.Roles.ALUMNI, UserId = "3", FullName = "Alumni2" } - } - } - } + new MemberForBookDto + { + Id = 1, RoleName = AuthConstants.Roles.ALUMNI, UserId = "1", FullName = "Alumni1" + }, + new MemberForBookDto + { + Id = 2, RoleName = AuthConstants.Roles.MEMBERS, UserId = "2", FullName = "Member1" + }, + new MemberForBookDto + { + Id = 3, RoleName = AuthConstants.Roles.ALUMNI, UserId = "3", FullName = "Alumni2" + } } - }; + } + } + } + }; } [Fact] @@ -56,7 +64,7 @@ public void CallCalculateBookRankForEachCategoryGivenCategoriesWithBooks() _rankAndOrderService.UpdateBooksRank(bookCategories); // Assert - _mockRankingService.Verify(rs => rs.CalculateBookRank(It.IsAny>()), Times.Exactly(bookCategories.Count)); + _mockRankingService.Received(bookCategories.Count).CalculateBookRank(Arg.Any>()); } [Fact] @@ -69,7 +77,7 @@ public void NotCallCalculateBookRankGivenCategoryWithoutBooks() _rankAndOrderService.UpdateBooksRank(bookCategories); // Assert - _mockRankingService.Verify(rs => rs.CalculateBookRank(It.IsAny>()), Times.Never()); + _mockRankingService.DidNotReceive().CalculateBookRank(Arg.Any>()); } [Fact] @@ -77,13 +85,13 @@ public void CallCalculateBookRankForEachCategoryGivenMultipleCategories() { // Arrange var bookCategories = GetTestBookCategories(); - bookCategories.Add(GetTestBookCategories().First()); + bookCategories.Add(GetTestBookCategories()[0]); // Act _rankAndOrderService.UpdateBooksRank(bookCategories); // Assert - _mockRankingService.Verify(rs => rs.CalculateBookRank(It.IsAny>()), Times.Exactly(bookCategories.Count)); + _mockRankingService.Received(bookCategories.Count).CalculateBookRank(Arg.Any>()); } [Fact] @@ -106,7 +114,7 @@ public void NotCallCalculateBookRankGivenEmptyBookCategories() _rankAndOrderService.UpdateBooksRank(bookCategories); // Assert - _mockRankingService.Verify(rs => rs.CalculateBookRank(It.IsAny>()), Times.Never()); + _mockRankingService.DidNotReceive().CalculateBookRank(Arg.Any>()); } [Fact] @@ -114,7 +122,7 @@ public void UpdateBooksRankGivenCategoriesWithMultipleBooks() { // Arrange var bookCategories = GetTestBookCategories(); - bookCategories.First().Books.Add(new BookDto + bookCategories[0].Books.Add(new BookDto { Id = 2, MembersWhoHaveRead = new List @@ -124,23 +132,20 @@ public void UpdateBooksRankGivenCategoriesWithMultipleBooks() } }); - _mockRankingService.Setup(rs => rs.CalculateBookRank(It.IsAny>())) - .Callback((List books) => + _mockRankingService.CalculateBookRank(Arg.Do>(books => + { + foreach (var book in books) { - foreach (var book in books) - { - book.Rank = book.Id!.Value; - } - }); + book.Rank = book.Id!.Value; + } + })); // Act _rankAndOrderService.UpdateBooksRank(bookCategories); // Assert - _mockRankingService.Verify(rs => rs.CalculateBookRank(It.IsAny>()), Times.Exactly(bookCategories.Count)); - Assert.Equal(1, bookCategories.First().Books.First().Rank); - Assert.Equal(2, bookCategories.First().Books.Last().Rank); + _mockRankingService.Received(bookCategories.Count).CalculateBookRank(Arg.Any>()); + Assert.Equal(1, bookCategories[0].Books[0].Rank); + Assert.Equal(2, bookCategories[0].Books[1].Rank); } - } - diff --git a/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/UpdateMembersReadRank.cs b/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/UpdateMembersReadRank.cs index 4eb4c2714..87fc12ac2 100644 --- a/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/UpdateMembersReadRank.cs +++ b/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/UpdateMembersReadRank.cs @@ -1,25 +1,25 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; using DevBetterWeb.Core; using DevBetterWeb.Web.Interfaces; using DevBetterWeb.Web.Models; using DevBetterWeb.Web.Services; using Xunit; -using Moq; -using System.Linq; -using System; +using NSubstitute; namespace DevBetterWeb.UnitTests.Web.Services.RankAndOrderServiceTests; public class UpdateMembersReadRank { - private readonly Mock _mockRankingService; + private readonly IRankingService _rankingService; private readonly RankAndOrderService _rankAndOrderService; public UpdateMembersReadRank() { - _mockRankingService = new Mock(); - var mockMemberService = new Mock(); - _rankAndOrderService = new RankAndOrderService(_mockRankingService.Object, mockMemberService.Object); + _rankingService = Substitute.For(); + var mockMemberService = Substitute.For(); + _rankAndOrderService = new RankAndOrderService(_rankingService, mockMemberService); } private List GetTestBookCategories() @@ -36,9 +36,18 @@ private List GetTestBookCategories() Id = 1, MembersWhoHaveRead = new List { - new MemberForBookDto { Id = 1, RoleName = AuthConstants.Roles.ALUMNI, UserId = "1", FullName = "Alumni1" }, - new MemberForBookDto { Id = 2, RoleName = AuthConstants.Roles.MEMBERS, UserId = "2", FullName = "Member1" }, - new MemberForBookDto { Id = 3, RoleName = AuthConstants.Roles.ALUMNI, UserId = "3", FullName = "Alumni2" } + new MemberForBookDto + { + Id = 1, RoleName = AuthConstants.Roles.ALUMNI, UserId = "1", FullName = "Alumni1" + }, + new MemberForBookDto + { + Id = 2, RoleName = AuthConstants.Roles.MEMBERS, UserId = "2", FullName = "Member1" + }, + new MemberForBookDto + { + Id = 3, RoleName = AuthConstants.Roles.ALUMNI, UserId = "3", FullName = "Alumni2" + } } } } @@ -58,8 +67,8 @@ public void CalculateMemberRankGivenBookCategoriesWithMembersAndAlumni() // Assert foreach (var category in bookCategories) { - _mockRankingService.Verify(rs => rs.CalculateMemberRank(category.Members), Times.AtLeastOnce()); - _mockRankingService.Verify(rs => rs.CalculateMemberRank(category.Alumnus), Times.AtLeastOnce()); + _rankingService.Received(1).CalculateMemberRank(category.Members); + _rankingService.Received(1).CalculateMemberRank(category.Alumnus); } } @@ -73,10 +82,9 @@ public void NotCallCalculateMemberRankGivenBookCategoriesWithoutBooks() _rankAndOrderService.UpdateMembersReadRank(bookCategories); // Assert - _mockRankingService.Verify(rs => rs.CalculateMemberRank(It.IsAny>()), Times.Never()); + _rankingService.DidNotReceive().CalculateMemberRank(Arg.Any>()); } - [Fact] public void CalculateMemberRankForEachCategoryGivenMultipleBookCategories() { @@ -88,7 +96,7 @@ public void CalculateMemberRankForEachCategoryGivenMultipleBookCategories() _rankAndOrderService.UpdateMembersReadRank(bookCategories); // Assert - _mockRankingService.Verify(rs => rs.CalculateMemberRank(It.IsAny>()), Times.Exactly(bookCategories.Count * 2)); + _rankingService.Received(bookCategories.Count * 2).CalculateMemberRank(Arg.Any>()); } [Fact] @@ -157,6 +165,6 @@ public void NotCallCalculateMemberRankGivenEmptyBookCategories() _rankAndOrderService.UpdateMembersReadRank(bookCategories); // Assert - _mockRankingService.Verify(rs => rs.CalculateMemberRank(It.IsAny>()), Times.Never()); + _rankingService.DidNotReceive().CalculateMemberRank(Arg.Any>()); } } diff --git a/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/UpdateRanksAndReadBooksCountForMemberAsync.cs b/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/UpdateRanksAndReadBooksCountForMemberAsync.cs index 5fe34d672..47e382b56 100644 --- a/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/UpdateRanksAndReadBooksCountForMemberAsync.cs +++ b/tests/DevBetterWeb.UnitTests/Web/Services/RankAndOrderServiceTests/UpdateRanksAndReadBooksCountForMemberAsync.cs @@ -4,7 +4,7 @@ using DevBetterWeb.Web.Models; using DevBetterWeb.Web.Services; using Xunit; -using Moq; +using NSubstitute; using System.Linq; using DevBetterWeb.Core; using DevBetterWeb.Core.Entities; @@ -13,14 +13,14 @@ namespace DevBetterWeb.UnitTests.Web.Services.RankAndOrderServiceTests; public class UpdateRanksAndReadBooksCountForMemberAsync { - private readonly Mock _mockMemberService; + private readonly IMemberService _memberService; private readonly RankAndOrderService _rankAndOrderService; public UpdateRanksAndReadBooksCountForMemberAsync() { - var mockRankingService = new Mock(); - _mockMemberService = new Mock(); - _rankAndOrderService = new RankAndOrderService(mockRankingService.Object, _mockMemberService.Object); + var mockRankingService = Substitute.For(); + _memberService = Substitute.For(); + _rankAndOrderService = new RankAndOrderService(mockRankingService, _memberService); } [Fact] @@ -28,32 +28,26 @@ public async Task UpdateMembersWhoHaveReadCountGivenBookCategories() { // Arrange var bookCategories = new List + { + new BookCategoryDto + { + Books = new List { - new BookCategoryDto + new BookDto + { + MembersWhoHaveRead = new List { new MemberForBookDto(), new MemberForBookDto() } + }, + new BookDto + { + MembersWhoHaveRead = new List { - Books = new List - { - new BookDto - { - MembersWhoHaveRead = new List - { - new MemberForBookDto(), - new MemberForBookDto() - } - }, - new BookDto - { - MembersWhoHaveRead = new List - { - new MemberForBookDto(), - new MemberForBookDto(), - new MemberForBookDto() - } - } - } + new MemberForBookDto(), new MemberForBookDto(), new MemberForBookDto() } - }; - _mockMemberService.Setup(x => x.GetActiveAlumniMembersAsync()).ReturnsAsync(new List { }); + } + } + } + }; + _memberService.GetActiveAlumniMembersAsync().Returns(new List { }); // Act await _rankAndOrderService.UpdateRanksAndReadBooksCountForMemberAsync(bookCategories); @@ -68,32 +62,32 @@ public async Task UpdateAlumniMembersGivenBookCategoriesAndActiveAlumniMembers() { // Arrange var bookCategories = new List + { + new BookCategoryDto + { + Books = new List { - new BookCategoryDto + new BookDto + { + MembersWhoHaveRead = new List { - Books = new List - { - new BookDto - { - MembersWhoHaveRead = new List - { - new MemberForBookDto { Id = 1 }, - new MemberForBookDto { Id = 2 } - } - }, - new BookDto - { - MembersWhoHaveRead = new List - { - new MemberForBookDto { Id = 3 }, - new MemberForBookDto { Id = 4 }, - new MemberForBookDto { Id = 1 } - } - } - } + new MemberForBookDto { Id = 1 }, new MemberForBookDto { Id = 2 } } - }; - _mockMemberService.Setup(x => x.GetActiveAlumniMembersAsync()).ReturnsAsync(new List { new Member { Id = 1 }, new Member { Id = 2 } }); + }, + new BookDto + { + MembersWhoHaveRead = new List + { + new MemberForBookDto { Id = 3 }, + new MemberForBookDto { Id = 4 }, + new MemberForBookDto { Id = 1 } + } + } + } + } + }; + _memberService.GetActiveAlumniMembersAsync() + .Returns(new List { new Member { Id = 1 }, new Member { Id = 2 } }); // Act await _rankAndOrderService.UpdateRanksAndReadBooksCountForMemberAsync(bookCategories); @@ -120,8 +114,7 @@ public async Task UpdateMemberRoleGivenBookCategoriesAndActiveAlumniMembers() { MembersWhoHaveRead = new List { - new MemberForBookDto { Id = 1 }, - new MemberForBookDto { Id = 2 } + new MemberForBookDto { Id = 1 }, new MemberForBookDto { Id = 2 } } }, new BookDto @@ -136,7 +129,8 @@ public async Task UpdateMemberRoleGivenBookCategoriesAndActiveAlumniMembers() } } }; - _mockMemberService.Setup(x => x.GetActiveAlumniMembersAsync()).ReturnsAsync(new List { new Member { Id = 5 }, new Member { Id = 6 } }); + _memberService.GetActiveAlumniMembersAsync() + .Returns(new List { new Member { Id = 5 }, new Member { Id = 6 } }); // Act await _rankAndOrderService.UpdateRanksAndReadBooksCountForMemberAsync(bookCategories); diff --git a/tests/DevBetterWeb.UnitTests/Web/Services/VideoDetailsServiceTests.cs b/tests/DevBetterWeb.UnitTests/Web/Services/VideoDetailsServiceTests.cs index eb10aeb01..88e81f950 100644 --- a/tests/DevBetterWeb.UnitTests/Web/Services/VideoDetailsServiceTests.cs +++ b/tests/DevBetterWeb.UnitTests/Web/Services/VideoDetailsServiceTests.cs @@ -1,11 +1,9 @@ using System.Collections.Generic; using FluentAssertions; using Flurl.Http.Testing; -using Moq; using Xunit; using DevBetterWeb.Web.Interfaces; using DevBetterWeb.Web.Services; -using NimblePros.Vimeo.Models; namespace DevBetterWeb.UnitTests.Web.Services; @@ -17,11 +15,12 @@ public class VideoDetailsServiceTests public async void GetTranscript_Returns_Empty_String_When_No_TextTracks() { List textTracks = new(); - var vttServiceMock = new Mock(); - vttServiceMock.Setup(x => x.Parse(It.IsAny(), It.IsAny(), It.IsAny())).Returns("test"); - var videoDetailsService = new VideoDetailsService(null!, null!, null!, null!, vttServiceMock.Object); + var vttServiceMock = Substitute.For(); + vttServiceMock.Parse(Arg.Any(), Arg.Any(), Arg.Any()).Returns("test"); + var videoDetailsService = new VideoDetailsService(null!, null!, null!, null!, vttServiceMock); - var result = await videoDetailsService.GetTranscriptAsync(textTracks, "https://it-does-not-matter-for-this-test.com"); + var result = + await videoDetailsService.GetTranscriptAsync(textTracks, "https://it-does-not-matter-for-this-test.com"); result.Should().BeEmpty(); } @@ -31,11 +30,12 @@ public async void GetTranscript_Returns_Empty_String_When_TextTrackLink_Is_Inval { List textTracks = new() { new TextTrack { Link = "I am most definitely not a valid url" } }; _httpTest.RespondWith("Me no findy", 404); - var vttServiceMock = new Mock(); - vttServiceMock.Setup(x => x.Parse(It.IsAny(), It.IsAny(), It.IsAny())).Returns("test"); - var videoDetailsService = new VideoDetailsService(null!, null!, null!, null!, vttServiceMock.Object); + var vttServiceMock = Substitute.For(); + vttServiceMock.Parse(Arg.Any(), Arg.Any(), Arg.Any()).Returns("test"); + var videoDetailsService = new VideoDetailsService(null!, null!, null!, null!, vttServiceMock); - var result = await videoDetailsService.GetTranscriptAsync(textTracks, "https://it-does-not-matter-for-this-test.com"); + var result = + await videoDetailsService.GetTranscriptAsync(textTracks, "https://it-does-not-matter-for-this-test.com"); result.Should().BeEmpty(); }