Refactor message service and move tests to Application.Tests

Renamed IMessageService to IMessageCommandService and updated all usages accordingly. Moved and renamed test files from Govor.API.Tests to the new Govor.Application.Tests project, updating namespaces to match. Refactored message-related services and controllers to use the new naming and structure. Added Govor.Application.Tests project to the solution.
This commit is contained in:
Artemy
2025-07-10 18:05:10 +07:00
parent a43a26b307
commit 65a43c09d3
33 changed files with 157 additions and 45 deletions
@@ -1,89 +0,0 @@
using AutoFixture;
using Govor.API.Services.AdminsStuff.Interfaces;
using Govor.Application.Interfaces.AdminsStuff;
using Govor.Core.Models;
using Govor.Core.Repositories.Invaites;
using Moq;
namespace Govor.API.Tests.UnitTests.Services.AdminStuff;
[TestFixture]
public class InvitationGeneratorTests
{
private Fixture _fixture;
private Mock<IInvitesRepository> _invitesRepositoryMock;
private IInvitationGenerator _invitationGenerator;
[SetUp]
public void SetUp()
{
_fixture = new Fixture();
_fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
_invitesRepositoryMock = new Mock<IInvitesRepository>();
_invitationGenerator = new InvitationGenerator(_invitesRepositoryMock.Object);
}
[Test]
public async Task GenerateInvitationCode_ShouldReturnNonEmptyString_WhenCalled()
{
// Arrange
var endDate = _fixture.Create<DateTime>();
var maxUsers = _fixture.Create<int>();
var isAdmin = _fixture.Create<bool>();
var description = _fixture.Create<string>();
// Act
var code = await _invitationGenerator.GenerateInvitationCode(endDate, maxUsers, isAdmin, description);
// Assert
Assert.That(code, Is.Not.Null.And.Not.Empty);
}
[Test]
public async Task GenerateInvitationCode_ShouldCallAddAsyncOnRepository_WithCorrectInvitation()
{
// Arrange
var endDate = DateTime.UtcNow.AddDays(7); // Specific date for easier assertion if needed
var maxUsers = 10;
var isAdmin = false;
var description = "Test Invitation";
Invitation capturedInvitation = null;
_invitesRepositoryMock.Setup(repo => repo.AddAsync(It.IsAny<Invitation>()))
.Callback<Invitation>(inv => capturedInvitation = inv)
.Returns(Task.CompletedTask);
// Act
var code = await _invitationGenerator.GenerateInvitationCode(endDate, maxUsers, isAdmin, description);
// Assert
_invitesRepositoryMock.Verify(repo => repo.AddAsync(It.IsAny<Invitation>()), Times.Once);
Assert.That(capturedInvitation, Is.Not.Null);
Assert.That(capturedInvitation.EndDate.ToUniversalTime(), Is.EqualTo(endDate.ToUniversalTime()));
Assert.That(capturedInvitation.MaxParticipants, Is.EqualTo(maxUsers));
Assert.That(capturedInvitation.IsAdmin, Is.EqualTo(isAdmin));
Assert.That(capturedInvitation.Description, Is.EqualTo(description));
Assert.That(capturedInvitation.Code, Is.EqualTo(code));
Assert.That(capturedInvitation.IsActive, Is.True); // Assuming new invitations are active by default
}
[Test]
public async Task GenerateInvitationCode_ShouldGenerateUniqueCode_WhenCalled()
{
// Arrange
var endDate = _fixture.Create<DateTime>();
var maxUsers = _fixture.Create<int>();
var isAdmin = _fixture.Create<bool>();
var description = _fixture.Create<string>();
// Act
var code1 = await _invitationGenerator.GenerateInvitationCode(endDate, maxUsers, isAdmin, description);
var code2 = await _invitationGenerator.GenerateInvitationCode(endDate, maxUsers, isAdmin, description);
// Assert
Assert.That(code1, Is.Not.EqualTo(code2));
}
}
@@ -1,102 +0,0 @@
using AutoFixture;
using Govor.Core.Infrastructure.Extensions;
using Govor.Core.Models;
using Govor.Core.Repositories.Users;
using Govor.API.Services.Authentication.Interfaces;
using Govor.Application.Exceptions.AuthService;
using Govor.Application.Interfaces.Authentication;
using Govor.Application.Services;
using Govor.Core.Repositories.Admins;
using Moq;
namespace Govor.API.Tests.UnitTests.Services.Authentication;
[TestFixture]
public class AuthServiceTests
{
private Fixture _fixture;
private Mock<IPasswordHasher> _passwordHasherMock;
private Mock<IJwtService> _jwtServiceMock;
private Mock<IUsersRepository> _usersRepositoryMock;
private Mock<IAdminsRepository> _adminsRepositoryMock;
private Mock<IUsernameValidator> _usernameValidatorMock;
private IAccountService _accountService;
[SetUp]
public void SetUp()
{
_fixture = new Fixture();
_fixture.Behaviors
.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
_usersRepositoryMock = new Mock<IUsersRepository>();
_passwordHasherMock = new Mock<IPasswordHasher>();
_jwtServiceMock = new Mock<IJwtService>();
_adminsRepositoryMock = new Mock<IAdminsRepository>();
_usernameValidatorMock = new Mock<IUsernameValidator>();
_accountService = new AuthService(
_usersRepositoryMock.Object,
_jwtServiceMock.Object,
_passwordHasherMock.Object,
_adminsRepositoryMock.Object,
_usernameValidatorMock.Object
);
}
[Test]
public void Given_ExistUser_When_Register_Should_Throw_UserAlreadyExistsException()
{
// Arrange
_usersRepositoryMock.Setup(r => r.ExistsUsernameAsync(It.IsAny<string>())).ReturnsAsync(true);
// Act & Assert
Assert.ThrowsAsync<UserAlreadyExistException>(async () => await _accountService.RegistrationAsync(
_fixture.Create<string>(), _fixture.Create<string>(), _fixture.Create<Invitation>()));
}
[Test]
public void Given_NotExistUser_When_Register_Should_Dont_Throw_UserNotRegisteredException()
{
// Arrange
_usersRepositoryMock.Setup(r => r.ExistsUsernameAsync(It.IsAny<string>())).ReturnsAsync(false);
// Act & Assert
Assert.DoesNotThrowAsync(async () => await _accountService.RegistrationAsync(
_fixture.Create<string>(), _fixture.Create<string>(), _fixture.Create<Invitation>()));
}
[Test]
public void Given_WrongPassword_When_Login_Should_Throw_LoginUserException()
{
// Arrange
_usersRepositoryMock.Setup(r => r.ExistsUsernameAsync(It.IsAny<string>())).ReturnsAsync(true);
_passwordHasherMock.Setup(h => h.Verify(It.IsAny<string>(),
It.IsAny<string>())).Returns(false);
_usersRepositoryMock.Setup(u => u.FindByUsernameAsync(It.IsAny<string>()))
.ReturnsAsync(() => _fixture.Create<User>());
// Act & Assert
Assert.ThrowsAsync<LoginUserException>(async () => await _accountService.LoginAsync(
_fixture.Create<string>(), _fixture.Create<string>()));
}
[Test]
public void Given_NotExistUser_When_Login_Should_Throw_UserNotRegisteredException()
{
// Arrange
_usersRepositoryMock.Setup(r => r.ExistsUsernameAsync(It.IsAny<string>())).ReturnsAsync(false);
// Act & Assert
Assert.ThrowsAsync<UserNotRegisteredException>(async () => await _accountService.LoginAsync(
_fixture.Create<string>(), _fixture.Create<string>()));
}
}
@@ -1,59 +0,0 @@
using System.IdentityModel.Tokens.Jwt;
using AutoFixture;
using Govor.API.Services.Authentication.Interfaces;
using Govor.Application.Services;
using Govor.Core.Models;
using Microsoft.Extensions.Options;
using Moq;
namespace Govor.API.Tests.UnitTests.Services.Authentication;
[TestFixture]
public class JwtServiceTests
{
private Fixture _fixture;
private Mock<IOptions<JwtOption>> _jwtOptionsMock;
private Mock<IInvitesService> _invitesServiceMock;
private IJwtService _jwtService;
private JwtOption _testJwtOptions;
[SetUp]
public void SetUp()
{
_fixture = new Fixture();
_fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
_testJwtOptions = new JwtOption
{
SecretKeу = "THIS IS A TEST SECRET KEY THAT IS LONG ENOUGH", // Ensure key size is sufficient for HMACSHA256
Hours = 1
};
_jwtOptionsMock = new Mock<IOptions<JwtOption>>();
_jwtOptionsMock.Setup(o => o.Value).Returns(_testJwtOptions);
_invitesServiceMock = new Mock<IInvitesService>();
_jwtService = new JwtService(_jwtOptionsMock.Object, _invitesServiceMock.Object);
}
[Test]
public async Task GenerateJwtToken_ShouldReturnValidJwtString()
{
// Arrange
var user = _fixture.Create<User>();
var expectedRole = "User";
_invitesServiceMock.Setup(s => s.GetRoleAsync(user)).Returns(Task.FromResult(expectedRole));
// Act
var tokenString = await _jwtService.GenerateJwtTokenAsync(user);
// Assert
Assert.That(tokenString, Is.Not.Null.And.Not.Empty);
// Attempt to parse the token to ensure it's a JWT
var handler = new JwtSecurityTokenHandler();
Assert.DoesNotThrow(() => handler.ReadJwtToken(tokenString));
}
}
@@ -1,106 +0,0 @@
using System.Security.Claims;
using Govor.Application.Infrastructure.Extensions;
using Microsoft.AspNetCore.Http;
using Moq;
namespace Govor.API.Tests.UnitTests.Services;
[TestFixture]
public class CurrentUserServiceTests
{
private Mock<IHttpContextAccessor> _httpContextAccessorMock;
private CurrentUserService _currentUserService;
[SetUp]
public void SetUp()
{
_httpContextAccessorMock = new Mock<IHttpContextAccessor>();
_currentUserService = new CurrentUserService(_httpContextAccessorMock.Object);
}
[Test]
public void GetCurrentUserId_ValidUserIdClaim_ReturnsGuid()
{
// Arrange
var userId = Guid.NewGuid();
var claims = new[] { new Claim("userId", userId.ToString()) };
var identity = new ClaimsIdentity(claims);
var principal = new ClaimsPrincipal(identity);
var httpContextMock = new Mock<HttpContext>();
httpContextMock.Setup(x => x.User).Returns(principal);
_httpContextAccessorMock.Setup(x => x.HttpContext).Returns(httpContextMock.Object);
// Act
var result = _currentUserService.GetCurrentUserId();
// Assert
Assert.That(result, Is.EqualTo(userId));
}
[Test]
public void GetCurrentUserId_NoHttpContext_ThrowsUnauthorizedAccessException()
{
// Arrange
_httpContextAccessorMock.Setup(x => x.HttpContext).Returns((HttpContext)null);
// Act & Assert
var ex = Assert.Throws<UnauthorizedAccessException>(() => _currentUserService.GetCurrentUserId());
Assert.That(ex.Message, Is.EqualTo("userID claim is missing or invalid"));
}
[Test]
public void GetCurrentUserId_NoUserIdClaim_ThrowsUnauthorizedAccessException()
{
// Arrange
var claims = new[] { new Claim("otherClaim", "value") };
var identity = new ClaimsIdentity(claims);
var principal = new ClaimsPrincipal(identity);
var httpContextMock = new Mock<HttpContext>();
httpContextMock.Setup(x => x.User).Returns(principal);
_httpContextAccessorMock.Setup(x => x.HttpContext).Returns(httpContextMock.Object);
// Act & Assert
var ex = Assert.Throws<UnauthorizedAccessException>(() => _currentUserService.GetCurrentUserId());
Assert.That(ex.Message, Is.EqualTo("userID claim is missing or invalid"));
}
[Test]
public void GetCurrentUserId_InvalidUserIdClaim_ThrowsUnauthorizedAccessException()
{
// Arrange
var claims = new[] { new Claim("userId", "invalid-guid") };
var identity = new ClaimsIdentity(claims);
var principal = new ClaimsPrincipal(identity);
var httpContextMock = new Mock<HttpContext>();
httpContextMock.Setup(x => x.User).Returns(principal);
_httpContextAccessorMock.Setup(x => x.HttpContext).Returns(httpContextMock.Object);
// Act & Assert
var ex = Assert.Throws<UnauthorizedAccessException>(() => _currentUserService.GetCurrentUserId());
Assert.That(ex.Message, Is.EqualTo("userID claim is missing or invalid"));
}
[Test]
public void GetCurrentUserId_EmptyUserIdClaim_ThrowsUnauthorizedAccessException()
{
// Arrange
var claims = new[] { new Claim("userId", "") };
var identity = new ClaimsIdentity(claims);
var principal = new ClaimsPrincipal(identity);
var httpContextMock = new Mock<HttpContext>();
httpContextMock.Setup(x => x.User).Returns(principal);
_httpContextAccessorMock.Setup(x => x.HttpContext).Returns(httpContextMock.Object);
// Act & Assert
var ex = Assert.Throws<UnauthorizedAccessException>(() => _currentUserService.GetCurrentUserId());
Assert.That(ex.Message, Is.EqualTo("userID claim is missing or invalid"));
}
}
@@ -1,285 +0,0 @@
using AutoFixture;
using Govor.Application.Exceptions.FriendsService;
using Govor.Application.Interfaces.Friends;
using Govor.Application.Services.Friends;
using Govor.Core.Models;
using Govor.Core.Repositories.Friendships;
using Govor.Core.Repositories.Users;
using Govor.Data.Repositories.Exceptions;
using Moq;
namespace Govor.API.Tests.UnitTests.Services.Friends;
[TestFixture]
public class FriendRequestCommandServiceTests
{
private Fixture _fixture;
private Mock<IUsersRepository> _usersRepositoryMock;
private Mock<IFriendshipsRepository> _friendshipsRepositoryMock;
private IFriendRequestCommandService _service;
[SetUp]
public void SetUp()
{
_fixture = new Fixture();
_fixture.Behaviors
.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
_usersRepositoryMock = new Mock<IUsersRepository>();
_friendshipsRepositoryMock = new Mock<IFriendshipsRepository>();
_service = new FriendRequestCommandService(_friendshipsRepositoryMock.Object);
}
// SendFriendRequestAsync
[Test]
public void SendFriendRequestAsync_SendingToSelf_ThrowsInvalidOperationException()
{
// Arrange
var userId = Guid.NewGuid();
// Act & Assert
var ex = Assert.ThrowsAsync<InvalidOperationException>(() =>
_service.SendAsync(userId, userId));
Assert.That(ex.Message, Is.EqualTo("Cannot send a request to self user"));
}
[Test]
public void SendFriendRequestAsync_RequestAlreadyExists_ThrowsRequestAlreadySentException()
{
// Arrange
var fromUserId = Guid.NewGuid();
var toUserId = Guid.NewGuid();
_friendshipsRepositoryMock
.Setup(repo => repo.Exist(fromUserId, toUserId))
.Returns(true);
// Act & Assert
Assert.ThrowsAsync<RequestAlreadySentException>(() =>
_service.SendAsync(fromUserId, toUserId));
}
[Test]
public async Task SendFriendRequestAsync_ValidRequest_CallsAddAsync()
{
// Arrange
var fromUserId = Guid.NewGuid();
var toUserId = Guid.NewGuid();
_friendshipsRepositoryMock
.Setup(repo => repo.Exist(fromUserId, toUserId))
.Returns(false);
// Act
await _service.SendAsync(fromUserId, toUserId);
// Assert
_friendshipsRepositoryMock.Verify(repo =>
repo.AddAsync(It.Is<Friendship>(f =>
f.RequesterId == fromUserId &&
f.AddresseeId == toUserId &&
f.Status == FriendshipStatus.Pending &&
f.Id != Guid.Empty
)),
Times.Once);
}
// AcceptFriendRequestAsync
[Test]
public async Task AcceptFriendRequestAsync_ValidRequest_CallsUpdateAsync()
{
var friendship = _fixture.Build<Friendship>()
.With(f => f.Status, FriendshipStatus.Pending)
.Create();
_friendshipsRepositoryMock
.Setup(r => r.GetByIdAsync(friendship.Id))
.ReturnsAsync(friendship);
// Act: вызываем именно Accept, не Send
await _service.AcceptAsync(friendship.Id, friendship.AddresseeId);
// Assert
_friendshipsRepositoryMock.Verify(r => r.UpdateAsync(It.Is<Friendship>(f =>
f.Id == friendship.Id &&
f.RequesterId == friendship.RequesterId &&
f.AddresseeId == friendship.AddresseeId &&
f.Status == FriendshipStatus.Accepted
)), Times.Once);
}
[Test]
public void AcceptFriendRequestAsync_Throws_InvalidOperationException_IfStatusNotEqualPending()
{
var friendship = _fixture.Build<Friendship>()
.With(f => f.Status, FriendshipStatus.Accepted)
.Create();
_friendshipsRepositoryMock
.Setup(r => r.GetByIdAsync(friendship.Id))
.ReturnsAsync(friendship);
// Act & Assert
Assert.ThrowsAsync<InvalidOperationException>(async () => await _service.AcceptAsync(friendship.Id, friendship.AddresseeId));
}
[Test]
public void AcceptFriendRequestAsync_Throws_UnauthorizedAccessException_IfCurrentUserIdIsNotAddressee()
{
// Arrange
var friendship = _fixture.Build<Friendship>()
.With(f => f.Status, FriendshipStatus.Pending)
.Create();
_friendshipsRepositoryMock
.Setup(r => r.GetByIdAsync(friendship.Id))
.ReturnsAsync(friendship);
var wrongUserId = Guid.NewGuid(); // не совпадает с AddresseeId
// Act & Assert
Assert.ThrowsAsync<UnauthorizedAccessException>(async () =>
await _service.AcceptAsync(friendship.Id, wrongUserId));
}
[Test]
public void AcceptFriendRequestAsync_Throws_InvalidOperationException_IfFriendshipNotFound()
{
// Arrange
var requestId = Guid.NewGuid();
var userId = Guid.NewGuid();
_friendshipsRepositoryMock
.Setup(r => r.GetByIdAsync(requestId))
.ThrowsAsync(new NotFoundByKeyException<Guid>(requestId));
// Act & Assert
Assert.ThrowsAsync<InvalidOperationException>(async () =>
await _service.AcceptAsync(requestId, userId));
}
[Test]
public async Task AcceptFriendRequestAsync_ChangesStatusToAccepted()
{
var friendship = _fixture.Build<Friendship>()
.With(f => f.Status, FriendshipStatus.Pending)
.Create();
_friendshipsRepositoryMock
.Setup(r => r.GetByIdAsync(friendship.Id))
.ReturnsAsync(friendship);
Friendship updatedFriendship = null;
_friendshipsRepositoryMock
.Setup(r => r.UpdateAsync(It.IsAny<Friendship>()))
.Callback<Friendship>(f => updatedFriendship = f)
.Returns(Task.CompletedTask);
await _service.AcceptAsync(friendship.Id, friendship.AddresseeId);
Assert.That(updatedFriendship.Status, Is.EqualTo(FriendshipStatus.Accepted));
}
// RejectFriend
[Test]
public async Task RejectFriendRequestAsync_ValidRequest_CallsRemoveAsync()
{
var friendship = _fixture.Build<Friendship>()
.With(f => f.Status, FriendshipStatus.Pending)
.Create();
_friendshipsRepositoryMock
.Setup(r => r.GetByIdAsync(friendship.Id))
.ReturnsAsync(friendship);
await _service.RejectAsync(friendship.Id, friendship.AddresseeId);
// Assert
_friendshipsRepositoryMock.Verify(r => r.UpdateAsync(It.Is<Friendship>(f =>
f.Id == friendship.Id &&
f.RequesterId == friendship.RequesterId &&
f.AddresseeId == friendship.AddresseeId &&
f.Status == FriendshipStatus.Rejected
)), Times.Once);
}
[Test]
public void RejectFriendRequestAsync_Throws_InvalidOperationException_IfStatusNotEqualPendingOrReject()
{
var friendship = _fixture.Build<Friendship>()
.With(f => f.Status, FriendshipStatus.Accepted)
.Create();
_friendshipsRepositoryMock
.Setup(r => r.GetByIdAsync(friendship.Id))
.ReturnsAsync(friendship);
// Act & Assert
Assert.ThrowsAsync<InvalidOperationException>(async () => await _service.RejectAsync(friendship.Id, friendship.AddresseeId));
}
[Test]
public void RejectFriendRequestAsync_Throws_UnauthorizedAccessException_IfCurrentUserIdIsNotAddressee()
{
// Arrange
var friendship = _fixture.Build<Friendship>()
.With(f => f.Status, FriendshipStatus.Pending)
.Create();
_friendshipsRepositoryMock
.Setup(r => r.GetByIdAsync(friendship.Id))
.ReturnsAsync(friendship);
var wrongUserId = Guid.NewGuid(); // не совпадает с AddresseeId
// Act & Assert
Assert.ThrowsAsync<UnauthorizedAccessException>(async () =>
await _service.RejectAsync(friendship.Id, wrongUserId));
}
[Test]
public void RejectFriendRequestAsync_Throws_InvalidOperationException_IfFriendshipNotFound()
{
// Arrange
var requestId = Guid.NewGuid();
var userId = Guid.NewGuid();
_friendshipsRepositoryMock
.Setup(r => r.GetByIdAsync(requestId))
.ThrowsAsync(new NotFoundByKeyException<Guid>(requestId));
// Act & Assert
Assert.ThrowsAsync<InvalidOperationException>(async () =>
await _service.RejectAsync(requestId, userId));
}
[Test]
public async Task RejectFriendRequestAsync_ChangesStatusToAccepted()
{
var friendship = _fixture.Build<Friendship>()
.With(f => f.Status, FriendshipStatus.Pending)
.Create();
_friendshipsRepositoryMock
.Setup(r => r.GetByIdAsync(friendship.Id))
.ReturnsAsync(friendship);
Friendship updatedFriendship = null;
_friendshipsRepositoryMock
.Setup(r => r.UpdateAsync(It.IsAny<Friendship>()))
.Callback<Friendship>(f => updatedFriendship = f)
.Returns(Task.CompletedTask);
await _service.RejectAsync(friendship.Id, friendship.AddresseeId);
Assert.That(updatedFriendship.Status, Is.EqualTo(FriendshipStatus.Rejected));
}
}
@@ -1,130 +0,0 @@
using AutoFixture;
using Govor.Application.Interfaces.Friends;
using Govor.Application.Services.Friends;
using Govor.Core.Models;
using Govor.Core.Repositories.Friendships;
using Govor.Core.Repositories.Users;
using Govor.Data.Repositories.Exceptions;
using Moq;
namespace Govor.API.Tests.UnitTests.Services.Friends;
[TestFixture]
public class FriendRequestQueryServiceTests
{
private Fixture _fixture;
private Mock<IUsersRepository> _usersRepositoryMock;
private Mock<IFriendshipsRepository> _friendshipsRepositoryMock;
private IFriendRequestQueryService _service;
[SetUp]
public void SetUp()
{
_fixture = new Fixture();
_fixture.Behaviors
.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
_usersRepositoryMock = new Mock<IUsersRepository>();
_friendshipsRepositoryMock = new Mock<IFriendshipsRepository>();
_service = new FriendRequestQueryService(_friendshipsRepositoryMock.Object);
}
// GetIncomingRequestsAsync
[Test]
public async Task GetIncomingRequestsAsync_ReturnsFriendships_IfFriendshipsExists()
{
// Arrange
var userId = Guid.NewGuid();
var friendships = _fixture.CreateMany<Friendship>().ToList();
var user = _fixture.Build<User>()
.With(u => u.Id, userId)
.With(u => u.ReceivedFriendRequests, friendships)
.Create();
friendships.ForEach(f =>
{
f.AddresseeId = userId;
f.Addressee = user;
f.Status = FriendshipStatus.Pending;
});
_friendshipsRepositoryMock.Setup(f => f.FindByUserIdAsync(userId))
.ReturnsAsync(friendships);
// Act
var result = await _service.GetIncomingAsync(userId);
// Assert
Assert.That(result.Count, Is.EqualTo(friendships.Count));
Assert.That(result.Select(u => u.Id), Is.EquivalentTo(friendships.Select(f => f.Id)));
}
[Test]
public void GetIncomingRequestsAsync_ThrowsInvalidOperationException_WhenUserNotFound()
{
// Arrange
var userId = Guid.NewGuid();
_friendshipsRepositoryMock
.Setup(r => r.FindByUserIdAsync(userId))
.ThrowsAsync(new NotFoundByKeyException<Guid>(userId));
// Act & Assert
Assert.ThrowsAsync<InvalidOperationException>(async () =>
await _service.GetIncomingAsync(userId));
}
// GetResponsesAsync
[Test]
public async Task GetResponsesAsync_ReturnsFriendships_IfFriendshipsExists()
{
// Arrange
var userId = Guid.NewGuid();
var friendships = _fixture.CreateMany<Friendship>().ToList();
var user = _fixture.Build<User>()
.With(u => u.Id, userId)
.With(u => u.ReceivedFriendRequests, friendships)
.Create();
friendships.ForEach(f =>
{
f.RequesterId = userId;
f.Requester = user;
f.Status = FriendshipStatus.Rejected;
});
_friendshipsRepositoryMock.Setup(f => f.FindByUserIdAsync(userId))
.ReturnsAsync(friendships);
// Act
var result = await _service.GetResponsesAsync(userId);
// Assert
Assert.That(result.Count, Is.EqualTo(friendships.Count));
Assert.That(result.Select(u => u.Id), Is.EquivalentTo(friendships.Select(f => f.Id)));
}
[Test]
public void GetResponsesAsync_ThrowsInvalidOperationException_WhenUserNotFound()
{
// Arrange
var userId = Guid.NewGuid();
_friendshipsRepositoryMock
.Setup(r => r.FindByUserIdAsync(userId))
.ThrowsAsync(new NotFoundByKeyException<Guid>(userId));
// Act & Assert
Assert.ThrowsAsync<InvalidOperationException>(async () =>
await _service.GetResponsesAsync(userId));
}
}
@@ -1,157 +0,0 @@
using AutoFixture;
using Govor.Application.Exceptions.FriendsService;
using Govor.Application.Interfaces.Friends;
using Govor.Application.Services.Friends;
using Govor.Core.Models;
using Govor.Core.Repositories.Friendships;
using Govor.Core.Repositories.Users;
using Govor.Data.Repositories.Exceptions;
using Moq;
namespace Govor.API.Tests.UnitTests.Services.Friends;
[TestFixture]
public class FriendshipServiceTests
{
private Fixture _fixture;
private Mock<IUsersRepository> _usersRepositoryMock;
private Mock<IFriendshipsRepository> _friendshipsRepositoryMock;
IFriendshipService _service;
[SetUp]
public void SetUp()
{
_fixture = new Fixture();
_fixture.Behaviors
.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
_usersRepositoryMock = new Mock<IUsersRepository>();
_friendshipsRepositoryMock = new Mock<IFriendshipsRepository>();
_service = new FriendshipService(_usersRepositoryMock.Object, _friendshipsRepositoryMock.Object);
}
// SearchUsersAsync
[Test]
public async Task SearchUsersAsync_ReturnsUsers_IfNotAlreadyFriends()
{
// Arrange
var userId = _fixture.Create<Guid>();
var user = _fixture.Create<User>();
user.Id = Guid.NewGuid();
_usersRepositoryMock
.Setup(u => u.SearchPotentialFriendsAsync(userId, It.IsAny<string>()))
.ReturnsAsync(new List<User> { user });
_friendshipsRepositoryMock
.Setup(f => f.FindByUserIdAsync(userId))
.ReturnsAsync(new List<Friendship>()); // No friends
// Act
var result = await _service.SearchUsersAsync("test", userId);
// Assert
Assert.That(result, Has.Count.EqualTo(1));
Assert.That(result[0].Id, Is.EqualTo(user.Id));
}
[Test]
public void SearchUsersAsync_Throws_SearchUsersException_IfThrowsNotFoundByKeyException_String_Guid()
{
// Arrange
_usersRepositoryMock
.Setup(u => u.SearchPotentialFriendsAsync(It.IsAny<Guid>(), It.IsAny<string>()))
.ThrowsAsync(new NotFoundByKeyException<(string,Guid)>(("test",Guid.NewGuid()),"test"));
// Axt & Assert
Assert.ThrowsAsync<SearchUsersException>(async () => await _service.SearchUsersAsync("test", Guid.NewGuid()));
}
[Test]
public async Task SearchUsersAsync_ReturnsUsersWithoutFriendships_IfThrowsNotFoundByKeyException_Guid()
{
// Arrange
var userId = _fixture.Create<Guid>();
var user = _fixture.Create<User>();
user.Id = Guid.NewGuid();
_usersRepositoryMock
.Setup(u => u.SearchPotentialFriendsAsync(userId, It.IsAny<string>()))
.ReturnsAsync(new List<User> { user });
_friendshipsRepositoryMock
.Setup(f => f.FindByUserIdAsync(userId))
.ThrowsAsync(new NotFoundByKeyException<Guid>(userId, "test"));
// Act
var result = await _service.SearchUsersAsync("test", userId);
// Assert
Assert.That(result, Has.Count.EqualTo(1));
Assert.That(result[0].Id, Is.EqualTo(user.Id));
}
[Test]
public void SearchUsersAsync_Throws_UnauthorizedAccessException_IfThrowsSomeExceptionInUsersRepository()
{
// Arrange
_usersRepositoryMock
.Setup(u => u.SearchPotentialFriendsAsync(It.IsAny<Guid>(), It.IsAny<string>()))
.ThrowsAsync(new Exception("test"));
// Act & Assert
Assert.ThrowsAsync<UnauthorizedAccessException>(async () => await _service.SearchUsersAsync("test", Guid.NewGuid()));
}
[Test]
public void SearchUsersAsync_Throws_UnauthorizedAccessException_IfThrowsSomeExceptionInFriendshipsRepository()
{
// Arrange
_friendshipsRepositoryMock
.Setup(u => u.FindByUserIdAsync(It.IsAny<Guid>()))
.ThrowsAsync(new Exception("test"));
// Act & Assert
Assert.ThrowsAsync<UnauthorizedAccessException>(async () => await _service.SearchUsersAsync("test", Guid.NewGuid()));
}
// GetFriendsAsync
[Test]
public async Task GetFriendsAsync_ReturnsUsers_IfUserExists()
{
// Arrange
var userId = Guid.NewGuid();
var friendships = _fixture.CreateMany<Friendship>().ToList();
friendships.ForEach(f =>
{
f.RequesterId = userId;
f.Status = FriendshipStatus.Accepted;
});
_friendshipsRepositoryMock.Setup(f => f.FindByUserIdAsync(userId))
.ReturnsAsync(friendships);
// Act
var result = await _service.GetFriendsAsync(userId);
// Assert
Assert.That(result.Count, Is.EqualTo(friendships.Count));
Assert.That(result, Is.EquivalentTo(friendships.Select(f => f.Addressee)));
}
[Test]
public void GetFriendsAsync_Throws_InvalidOperationException_IfUserNotExists()
{
// Arrange
_friendshipsRepositoryMock.Setup(f => f.FindByUserIdAsync(It.IsAny<Guid>()))
.ThrowsAsync(new NotFoundByKeyException<Guid>(Guid.NewGuid()));
// Act & Assert
Assert.ThrowsAsync<InvalidOperationException>(async () => await _service.GetFriendsAsync(Guid.NewGuid()));
}
}
@@ -1,140 +0,0 @@
using AutoFixture;
using Govor.Application.Interfaces;
using Govor.Application.Services;
using Microsoft.AspNetCore.Hosting;
using Moq;
namespace Govor.API.Tests.UnitTests.Services;
[TestFixture]
public class LocalStorageServiceTests
{
private Fixture _fixture;
private IStorageService _service;
private Mock<IWebHostEnvironment> _webHostEnvironmentMock;
private string _tempDirectory;
[SetUp]
public void SetUp()
{
_fixture = new Fixture();
_webHostEnvironmentMock = new Mock<IWebHostEnvironment>();
_tempDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(_tempDirectory);
_webHostEnvironmentMock.Setup(w => w.ContentRootPath).Returns(_tempDirectory);
_service = new LocalStorageService(_webHostEnvironmentMock.Object.ContentRootPath);
}
[TearDown]
public void TearDown()
{
if (Directory.Exists(_tempDirectory))
{
Directory.Delete(_tempDirectory, true);
}
}
[Test]
public async Task Given_ValidDataAndFileName_When_SaveAsync_Then_FileIsSaved()
{
// Arrange
var data = _fixture.CreateMany<byte>(1000).ToArray();
var fileName = _fixture.Create<string>() + ".txt";
var saveDate = DateTime.UtcNow;
// Act
var url = await _service.SaveAsync(data, fileName);
// Assert
Assert.That(url, Is.Not.Null);
// _tempDirectory/uploads/yyyy/MM/url
var datePath = saveDate.ToString("yyyy/MM");
var expectedFilePath = Path.Combine(_tempDirectory, "uploads", url);
Assert.That(File.Exists(expectedFilePath), Is.True);
}
[Test]
public void Given_EmptyName_When_SaveAsync_Should_Throw_ArgumentException()
{
// Arrange
var data = _fixture.CreateMany<byte>(1000).ToArray();
// Act & Assert
Assert.ThrowsAsync<ArgumentException>(async () => await _service.SaveAsync(data, string.Empty));
}
[Test]
public void Given_EmptyData_When_SaveAsync_Should_Throw_ArgumentException()
{
// Arrange
var name = _fixture.Create<string>();
// Act & Assert
Assert.ThrowsAsync<ArgumentException>(async () => await _service.SaveAsync(default, name));
}
[Test]
public async Task Given_ValidUrl_When_LoadAsync_Then_Returns_FileStream()
{
// Arrange
var date = DateTime.UtcNow.ToString("yyyy/MM");
var corePath = Path.Combine(_tempDirectory, "uploads", date);
Directory.CreateDirectory(corePath);
var fileName = _fixture.Create<string>() + ".txt";
var fileContent = _fixture.Create<string>();
var filePath = Path.Combine(corePath, fileName);
await File.WriteAllTextAsync(filePath, fileContent);
// Act
var url = Path.Combine(date, fileName);
await using var stream = await _service.LoadAsync(url);
// Assert
Assert.That(stream, Is.Not.Null);
Assert.That(stream.Length, Is.GreaterThan(0));
// Дополнительная проверка: содержимое файла
using var reader = new StreamReader(stream);
var content = await reader.ReadToEndAsync();
Assert.That(content, Is.EqualTo(fileContent));
}
[Test]
public void Given_EmptyUrl_When_LoadAsync_Should_Throw_FileNotFoundException()
{
// Act & Assert
Assert.ThrowsAsync<FileNotFoundException>(async () => await _service.LoadAsync(_fixture.Create<string>()+".txt"));
}
[Test]
public async Task Given_ValidUrl_When_DeleteAsync_Then_FileIsDeleted()
{
// Arrange
var date = DateTime.UtcNow.ToString("yyyy/MM");
var corePath = Path.Combine(_tempDirectory, "uploads", date);
Directory.CreateDirectory(corePath);
var fileName = _fixture.Create<string>() + ".txt";
var fileContent = _fixture.Create<string>();
var filePath = Path.Combine(corePath, fileName);
await File.WriteAllTextAsync(filePath, fileContent);
// Act
var url = Path.Combine(date, fileName);
await _service.RemoveAsync(url);
Assert.That(File.Exists(filePath), Is.False);
}
[Test]
public async Task Given_InvalidUrl_When_DeleteAsync_TShould_Not_Throw()
{
// Act & Assert
Assert.DoesNotThrowAsync(async () => await _service.RemoveAsync(_fixture.Create<string>()+".txt"));
}
}
@@ -1,325 +0,0 @@
using Govor.Application.Exceptions.VerifyFriendship;
using Govor.Application.Interfaces;
using Govor.Application.Interfaces.Messages.Parameters;
using Govor.Application.Services;
using Govor.Core.Models;
using Govor.Core.Repositories.Groups;
using Govor.Core.Repositories.Messages;
using Govor.Core.Repositories.PrivateChats;
using Govor.Core.Repositories.Users;
using Govor.Data.Repositories.Exceptions;
using Microsoft.Extensions.Logging;
using Moq;
namespace Govor.API.Tests.UnitTests.Services;
[TestFixture]
public class MessageServiceTests
{
private Mock<IMessagesRepository> _mockMessagesRepo;
private Mock<IUsersRepository> _mockUsersRepo;
private Mock<IGroupsRepository> _mockGroupsRepo;
private Mock<IVerifyFriendship> _mockVerifyFriendship;
private Mock<IPrivateChatsRepository> _mockPrivateChats;
private Mock<ILogger<MessageService>> _mockLogger;
private MessageService _messageService;
[SetUp]
public void SetUp()
{
_mockMessagesRepo = new Mock<IMessagesRepository>();
_mockUsersRepo = new Mock<IUsersRepository>();
_mockGroupsRepo = new Mock<IGroupsRepository>();
_mockVerifyFriendship = new Mock<IVerifyFriendship>();
_mockPrivateChats = new Mock<IPrivateChatsRepository>();
_mockLogger = new Mock<ILogger<MessageService>>();
_messageService = new MessageService(
_mockMessagesRepo.Object,
_mockUsersRepo.Object,
_mockGroupsRepo.Object,
_mockVerifyFriendship.Object,
_mockPrivateChats.Object,
_mockLogger.Object);
}
// Test for SendMessageAsync action
[Test]
public async Task SendMessageAsync_ToUser_Success()
{
// Arrange
var senderId = Guid.NewGuid();
var recipientId = Guid.NewGuid();
var sendMessageParams = new SendMessage("Hello",
null,
recipientId,
RecipientType.User,
senderId,
DateTime.UtcNow,
new List<SendMedia>());
_mockUsersRepo.Setup(r => r.ExistsByIdAsync(recipientId)).ReturnsAsync(true);
_mockVerifyFriendship.Setup(v => v.VerifyAsync(senderId, recipientId)).Returns(Task.CompletedTask);
_mockMessagesRepo.Setup(r => r.AddAsync(It.IsAny<Message>())).Returns(Task.CompletedTask);
_mockPrivateChats.Setup(c => c.Exist(senderId, recipientId)).Returns(true);
_mockPrivateChats.Setup(c => c.GetByMembersAsync(senderId, recipientId)).ReturnsAsync(new PrivateChat(){Id = recipientId});
// Act
var result = await _messageService.SendMessageAsync(sendMessageParams);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.IsSuccess, Is.True);
Assert.That(result.Exception, Is.Null);
_mockMessagesRepo.Verify(r => r.AddAsync(It.Is<Message>(m =>
m.SenderId == senderId &&
m.RecipientId == recipientId &&
m.RecipientType == RecipientType.User &&
m.EncryptedContent == "Hello")), Times.Once);
}
[Test]
public async Task SendMessageAsync_ToGroup_Success()
{
// Arrange
var senderId = Guid.NewGuid();
var groupId = Guid.NewGuid();
var sendMessageParams = new SendMessage("Hello Group",
null,
groupId,
RecipientType.Group,
senderId,
DateTime.UtcNow,
new List<SendMedia>());
_mockGroupsRepo.Setup(r => r.Exist(groupId)).Returns(true);
_mockGroupsRepo.Setup(r => r.IsUserMemberOfGroupAsync(senderId, groupId)).ReturnsAsync(true);
_mockMessagesRepo.Setup(r => r.AddAsync(It.IsAny<Message>())).Returns(Task.CompletedTask);
// Act
var result = await _messageService.SendMessageAsync(sendMessageParams);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.IsSuccess, Is.True);
Assert.That(result.Exception, Is.Null);
_mockMessagesRepo.Verify(r => r.AddAsync(It.Is<Message>(m =>
m.RecipientId == groupId &&
m.RecipientType == RecipientType.Group)), Times.Once);
}
[Test]
public async Task SendMessageAsync_ToUser_RecipientNotFound_ReturnsFailure()
{
// Arrange
var senderId = Guid.NewGuid();
var recipientId = Guid.NewGuid();
var sendMessageParams = new SendMessage("Hello",
null,
recipientId,
RecipientType.User,
senderId,
DateTime.UtcNow,
new List<SendMedia>());
_mockUsersRepo.Setup(r => r.ExistsByIdAsync(recipientId)).ReturnsAsync(false);
// Act
var result = await _messageService.SendMessageAsync(sendMessageParams);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.IsSuccess, Is.False);
Assert.That(result.Exception, Is.Not.Null);
Assert.That(result.Exception,Is.TypeOf<KeyNotFoundException>());
Assert.That(result.Message, Is.Null);
}
[Test]
public async Task SendMessageAsync_ToUser_FriendshipVerificationFails_ReturnsFailure()
{
// Arrange
var senderId = Guid.NewGuid();
var recipientId = Guid.NewGuid();
var sendMessageParams = new SendMessage("Hello",
null,
recipientId,
RecipientType.User,
senderId,
DateTime.UtcNow,
new List<SendMedia>()
);
_mockUsersRepo.Setup(r => r.ExistsByIdAsync(recipientId)).ReturnsAsync(true);
_mockVerifyFriendship.Setup(v => v.VerifyAsync(senderId, recipientId)).ThrowsAsync(new FriendshipException("Not friends"));
// Act
var result = await _messageService.SendMessageAsync(sendMessageParams);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.IsSuccess, Is.False);
Assert.That(result.Exception, Is.Not.Null);
Assert.That(result.Exception,Is.TypeOf<FriendshipException>());
Assert.That(result.Message, Is.Null);
}
// Test for EditMessageAsync action
[Test]
public async Task EditMessageAsync_Success()
{
// Arrange
var editorId = Guid.NewGuid();
var messageId = Guid.NewGuid();
var originalMessage = new Message
{
Id = messageId,
SenderId = editorId,
EncryptedContent = "Old",
RecipientId = Guid.NewGuid(),
RecipientType = RecipientType.User
};
var editParams = new EditMessage(editorId, messageId, "New Content", DateTime.UtcNow);
_mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).ReturnsAsync(originalMessage);
_mockMessagesRepo.Setup(r => r.UpdateAsync(It.IsAny<Message>())).Returns(Task.CompletedTask);
// Act
var result = await _messageService.EditMessageAsync(editParams);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.IsSuccess, Is.True);
Assert.That(result.OriginalMessage, Is.Not.Null);
Assert.That(messageId, Is.EqualTo(result.OriginalMessage!.Id));
_mockMessagesRepo.Verify(r => r.UpdateAsync(It.Is<Message>(m =>
m.Id == messageId &&
m.EncryptedContent == "New Content" &&
m.IsEdited == true &&
m.EditedAt == editParams.EditedAt)), Times.Once);
}
[Test]
public async Task EditMessageAsync_MessageNotFound_ReturnsFailure()
{
// Arrange
var editorId = Guid.NewGuid();
var messageId = Guid.NewGuid();
var editParams = new EditMessage(editorId, messageId, "New Content", DateTime.UtcNow);
_mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).
ThrowsAsync(new NotFoundByKeyException<Guid>(messageId));
// Act
var result = await _messageService.EditMessageAsync(editParams);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.IsSuccess, Is.False);
Assert.That(result.Exception, Is.Not.Null);
Assert.That(result.Exception,Is.TypeOf<NotFoundByKeyException<Guid>>());
Assert.That(result.OriginalMessage, Is.Null);
}
[Test]
public async Task EditMessageAsync_NotSender_ReturnsFailure()
{
// Arrange
var editorId = Guid.NewGuid();
var senderId = Guid.NewGuid(); // Different from editorId
var messageId = Guid.NewGuid();
var originalMessage = new Message { Id = messageId, SenderId = senderId, EncryptedContent = "Old" };
var editParams = new EditMessage(editorId, messageId, "New Content", DateTime.UtcNow);
_mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).ReturnsAsync(originalMessage);
// Act
var result = await _messageService.EditMessageAsync(editParams);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.IsSuccess, Is.False);
Assert.That(result.Exception, Is.Not.Null);
Assert.That(result.Exception,Is.TypeOf<UnauthorizedAccessException>());
Assert.That(result.OriginalMessage, Is.Null);
}
// Test for DeleteMessageAsync action
[Test]
public async Task DeleteMessageAsync_Success()
{
// Arrange
var deleterId = Guid.NewGuid();
var messageId = Guid.NewGuid();
var originalMessage = new Message { Id = messageId, SenderId = deleterId, RecipientId = Guid.NewGuid(), RecipientType = RecipientType.User };
var deleteParams = new DeleteMessage(deleterId, messageId);
_mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).ReturnsAsync(originalMessage);
_mockMessagesRepo.Setup(r => r.RemoveAsync(messageId)).Returns(Task.CompletedTask);
// Act
var result = await _messageService.DeleteMessageAsync(deleteParams);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.IsSuccess, Is.True);
Assert.That(result.OriginalMessage, Is.Not.Null);
Assert.That(messageId, Is.EqualTo(result.OriginalMessage!.Id));
_mockMessagesRepo.Verify(r => r.RemoveAsync(messageId), Times.Once);
}
[Test]
public async Task DeleteMessageAsync_MessageNotFound_ReturnsFailure()
{
// Arrange
var deleterId = Guid.NewGuid();
var messageId = Guid.NewGuid();
var deleteParams = new DeleteMessage(deleterId, messageId);
_mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).
ThrowsAsync(new NotFoundByKeyException<Guid>(messageId));
// Act
var result = await _messageService.DeleteMessageAsync(deleteParams);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.IsSuccess, Is.False);
Assert.That(result.Exception, Is.Not.Null);
Assert.That(result.Exception,Is.TypeOf<NotFoundByKeyException<Guid>>());
Assert.That(result.OriginalMessage, Is.Null);
}
[Test]
public async Task DeleteMessageAsync_NotSender_ReturnsFailure()
{
// Arrange
var deleterId = Guid.NewGuid();
var senderId = Guid.NewGuid(); // Different
var messageId = Guid.NewGuid();
var originalMessage = new Message { Id = messageId, SenderId = senderId };
var deleteParams = new DeleteMessage(deleterId, messageId);
_mockMessagesRepo.Setup(r => r.FindByIdAsync(messageId)).ReturnsAsync(originalMessage);
// Act
var result = await _messageService.DeleteMessageAsync(deleteParams);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.IsSuccess, Is.False);
Assert.That(result.Exception, Is.Not.Null);
Assert.That(result.Exception,Is.TypeOf<UnauthorizedAccessException>());
Assert.That(result.OriginalMessage, Is.Null);
}
}
@@ -1,51 +0,0 @@
using AutoFixture;
using Govor.Application.Services;
using Govor.Core.Infrastructure.Extensions;
namespace Govor.API.Tests.UnitTests.Services;
[TestFixture]
public class PasswordHasherTests
{
private IPasswordHasher _passwordHasher;
private Fixture _fixture;
[SetUp]
public void StarUp()
{
_fixture = new Fixture();
_passwordHasher = new PasswordHasher();
}
[Test]
public void Given_Password_When_Hash_Then_Hash_And_Verify_Then_Result_Should_Be_True()
{
// Arrange
string password = _fixture.Create<string>();
// Act
string hash = _passwordHasher.Hash(password);
var result = _passwordHasher.Verify(password, hash);
// Assert
Assert.That(hash, Is.Not.EqualTo(password));
Assert.That(result, Is.True);
}
[Test]
public void Given_Password_NotPassword_When_Hash_Should_Not_Be_True_Then_Result_Should_Be_False()
{
// Arrange
string password = _fixture.Create<string>();
string notPassword = _fixture.Create<string>();
// Act
string hash = _passwordHasher.Hash(password);
var result = _passwordHasher.Verify(notPassword, hash);
// Assert
Assert.That(result, Is.False);
}
}
@@ -1,58 +0,0 @@
using Govor.Application.Services;
using Govor.Core.Models;
using Govor.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
namespace Govor.API.Tests.UnitTests.Services;
[TestFixture]
public class PingHandlerServiceTests
{
private GovorDbContext _dbContext = null!;
private IMemoryCache _memoryCache = null!;
private PingHandlerService _service = null!;
private Guid _userId;
[SetUp]
public void SetUp()
{
var options = new DbContextOptionsBuilder<GovorDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
_dbContext = new GovorDbContext(options);
_memoryCache = new MemoryCache(new MemoryCacheOptions());
_service = new PingHandlerService(_dbContext, _memoryCache);
_userId = Guid.NewGuid();
_dbContext.Users.Add(new User
{
Id = _userId,
Username = "TestUser",
WasOnline = DateTime.UtcNow.AddHours(-1),
Description = "Test description",
PasswordHash = "hashed_password_here"
});
_dbContext.SaveChanges();
}
[Test]
public async Task Ping_DoesNotUpdate_WhenPingTooRecent()
{
// Arrange
var initial = DateTime.UtcNow.AddMinutes(-1);
_memoryCache.Set($"LastPing_{_userId}", DateTime.UtcNow);
var user = await _dbContext.Users.FirstAsync(u => u.Id == _userId);
var originalTime = user.WasOnline;
// Act
await _service.Ping(_userId);
var updatedUser = await _dbContext.Users.FirstAsync(u => u.Id == _userId);
// Assert
Assert.That(updatedUser.WasOnline, Is.EqualTo(originalTime));
}
}
@@ -1,70 +0,0 @@
using AutoFixture;
using Govor.Application.Interfaces;
using Govor.Application.Services;
using Govor.Core.Models;
using Govor.Core.Repositories.Groups;
using Govor.Data.Repositories.Exceptions;
using Moq;
namespace Govor.API.Tests.UnitTests.Services;
[TestFixture]
public class UserGroupsServiceTests
{
private Fixture _fixture;
private Mock<IGroupsRepository> _repositoryMock;
private IUserGroupsService _service;
[SetUp]
public void SetUp()
{
_fixture = new Fixture();
_fixture.Behaviors
.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
_repositoryMock = new Mock<IGroupsRepository>();
_service = new UserGroupsService(_repositoryMock.Object);
}
[Test]
public async Task GetUserGroups_ShouldReturnAllUserGroups()
{
// Arrange
var chats = _fixture.CreateMany<ChatGroup>();
var userId = chats.First().Members.First().Id;
_repositoryMock.Setup(r => r.GetByUserIdAsync(userId))
.ReturnsAsync([chats.First()]);
// Act
var result = await _service.GetUserGroupsAsync(userId);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.Count(), Is.EqualTo(1));
Assert.That(result, Is.EquivalentTo([chats.First()]));
}
[Test]
public async Task GetUserGroups_ButGroupDoesNotExist_ShouldReturnEmptyList()
{
// Arrange
var userId = _fixture.Create<Guid>();
_repositoryMock.Setup(r => r.GetByUserIdAsync(userId))
.ThrowsAsync(new NotFoundByKeyException<Guid>(userId));
// Act
var result = await _service.GetUserGroupsAsync(userId);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.Count(), Is.EqualTo(0));
}
}
@@ -1,43 +0,0 @@
using Govor.Application.Exceptions.AuthService;
using Govor.Application.Infrastructure.Validators;
namespace Govor.API.Tests.UnitTests.Services.Validators;
[TestFixture]
public class UsernameValidatorTests
{
private UsernameValidator _validator;
[SetUp]
public void SetUp()
{
_validator = new UsernameValidator();
}
[TestCase("Иван")]
[TestCase("Алексей")]
[TestCase("Ёжик")]
[TestCase("Иван123")] // содержит цифры
public void Validate_ValidUsernames_ShouldNotThrow(string username)
{
Assert.DoesNotThrow(() => _validator.Validate(username));
}
[TestCase("Ivan")] // не кириллица
[TestCase("123Иван")] // начинается не с буквы
[TestCase("!@#$")] // спецсимволы
[TestCase("")] // пусто
[TestCase("И")] // меньше минимума
[TestCase("ИванИванИванИванИванИванИванИванИванИванИванИванИван")] // больше максимума (44 символа)
public void Validate_InvalidUsernames_ShouldThrow(string username)
{
Assert.Throws<InvalidUsernameException>(() => _validator.Validate(username));
}
[TestCase("Иван", ExpectedResult = true)]
[TestCase("1234", ExpectedResult = false)]
public bool TryValidate_ShouldReturnTrueRegardlessOfInput(string username)
{
return _validator.TryValidate(username);
}
}
@@ -1,96 +0,0 @@
using AutoFixture;
using Govor.Application.Exceptions.VerifyFriendship;
using Govor.Application.Services;
using Govor.Core.Models;
using Govor.Core.Repositories.Friendships;
using Govor.Data.Repositories.Exceptions;
using Microsoft.Extensions.Logging;
using Moq;
namespace Govor.API.Tests.UnitTests.Services;
[TestFixture]
public class VerifyFriendshipTests
{
private Fixture _fixture;
private Mock<ILogger<VerifyFriendship>> _mockLogger;
private Mock<IFriendshipsRepository> _mockFriendships;
private VerifyFriendship _service;
[SetUp]
public void SetUp()
{
_fixture = new Fixture();
_fixture.Behaviors
.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
_mockLogger = new Mock<ILogger<VerifyFriendship>>();
_mockFriendships = new Mock<IFriendshipsRepository>();
_service = new VerifyFriendship(_mockFriendships.Object, _mockLogger.Object);
}
// Test for VerifyAsync action
[Test]
public async Task VerifyAsync_Success()
{
// Arrange
var friendship1 = _fixture.Create<Friendship>();
friendship1.Status = FriendshipStatus.Accepted;
_mockFriendships.Setup(f => f.FindByUserIdAsync(friendship1.RequesterId))
.ReturnsAsync([friendship1]);
// Act
await _service.VerifyAsync(friendship1.RequesterId, friendship1.AddresseeId);
// Assert
_mockFriendships.Verify(f => f.FindByUserIdAsync(friendship1.RequesterId), Times.Once());
Assert.That(await _service.TryVerifyAsync(friendship1.RequesterId, friendship1.AddresseeId), Is.EqualTo(true));
}
[Test]
public async Task VerifyAsync_IDsEmpty()
{
// Arrange
var friendship1 = _fixture.Create<Friendship>();
friendship1.RequesterId = Guid.Empty;
friendship1.AddresseeId = Guid.Empty;
// Act & Assert
Assert.ThrowsAsync<ArgumentException>(() => _service.VerifyAsync(friendship1.RequesterId, friendship1.AddresseeId));
Assert.That(await _service.TryVerifyAsync(friendship1.RequesterId, friendship1.AddresseeId), Is.EqualTo(false));
}
[Test]
public async Task VerifyAsync_ThrowsNotFoundByKeyException_ThrowsFriendshipException()
{
// Arrange
var friendship1 = _fixture.Create<Friendship>();
friendship1.Status = FriendshipStatus.Accepted;
_mockFriendships.Setup(f => f.FindByUserIdAsync(friendship1.RequesterId))
.ThrowsAsync(new NotFoundByKeyException<Guid>(friendship1.RequesterId));
// Act & Assert
Assert.ThrowsAsync<FriendshipException>(async () => await _service.VerifyAsync(friendship1.RequesterId, friendship1.AddresseeId));
_mockFriendships.Verify(f => f.FindByUserIdAsync(friendship1.RequesterId), Times.Once());
Assert.That(await _service.TryVerifyAsync(friendship1.RequesterId, friendship1.AddresseeId), Is.EqualTo(false));
}
[Test]
public async Task VerifyAsync_ReturnsEmptyFriendships_ThrowsFriendshipException()
{
// Arrange
var friendship1 = _fixture.Create<Friendship>();
friendship1.Status = FriendshipStatus.Accepted;
_mockFriendships.Setup(f => f.FindByUserIdAsync(friendship1.RequesterId))
.ReturnsAsync(new List<Friendship>());
// Act & Assert
Assert.ThrowsAsync<FriendshipException>(async () => await _service.VerifyAsync(friendship1.RequesterId, friendship1.AddresseeId));
_mockFriendships.Verify(f => f.FindByUserIdAsync(friendship1.RequesterId), Times.Once());
Assert.That(await _service.TryVerifyAsync(friendship1.RequesterId, friendship1.AddresseeId), Is.EqualTo(false));
}
}