using AutoFixture; using Govor.API.Controllers; using Govor.Application.Exceptions.FriendsService; using Govor.Application.Interfaces; using Govor.Application.Interfaces.Infrastructure.Extensions; using Govor.Contracts.DTOs; using Govor.Core.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Moq; namespace Govor.API.Tests.IntegrationTests.Controllers; [TestFixture] public class FriendsControllerTests { private Fixture _fixture; private Mock> _loggerMock; private Mock _friendsServiceMock; private Mock _currentUserServiceMock; private FriendsController _controller; [SetUp] public void SetUp() { _fixture = new Fixture(); _fixture.Behaviors.OfType().ToList().ForEach(b => _fixture.Behaviors.Remove(b)); _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); _loggerMock = new Mock>(); _friendsServiceMock = new Mock(); _currentUserServiceMock = new Mock(); _controller = new FriendsController( _loggerMock.Object, _friendsServiceMock.Object, _currentUserServiceMock.Object ); } // Tests for Search action [Test] public async Task Search_ValidRequest_ReturnsOkResult() { var users = _fixture.CreateMany().ToList(); var userId = _fixture.Create(); var query = _fixture.Create(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()).Returns(userId); _friendsServiceMock.Setup(f => f.SearchUsersAsync(query, userId)) .ReturnsAsync(users); // Act var result = await _controller.Search(query); var okResult = result as OkObjectResult; dynamic value = okResult.Value; List userDtos = value as List; // Assert Assert.That(value, Is.Not.Null); Assert.That(value.Count, Is.EqualTo(users.Count)); Assert.That(userDtos.Select(u => u.Id), Is.EqualTo(users.Select(u => u.Id))); } [Test] public async Task Search_InvalidQuery_BadRequest() { // Act var result = await _controller.Search(string.Empty); // Assert Assert.That(result, Is.InstanceOf()); var badRequestResult = result as BadRequestObjectResult; Assert.That(badRequestResult.Value, Is.EqualTo("Query cannot be empty")); } [Test] public async Task Search_NotFound_IfThrowsSearchUsersException() { // Arrange _friendsServiceMock.Setup(f => f.SearchUsersAsync(It.IsAny(), It.IsAny())) .ThrowsAsync(new SearchUsersException(_fixture.Create())); // Act var result = await _controller.Search(_fixture.Create()); // Assert Assert.That(result, Is.InstanceOf()); } [Test] public async Task Search_StatusCode500_IfThrowsSomeException() { // Arrange _friendsServiceMock.Setup(f => f.SearchUsersAsync(It.IsAny(), It.IsAny())) .ThrowsAsync(new Exception(_fixture.Create())); // Act var result = await _controller.Search(_fixture.Create()); // Assert Assert.That(result, Is.InstanceOf()); var objectResult = result as ObjectResult; Assert.That(objectResult.StatusCode, Is.EqualTo(500)); } // Test for SendRequest action [Test] public async Task SendRequest_ValidRequest_ReturnsOk() { var targetUserId = Guid.NewGuid(); var result = await _controller.SendRequest(targetUserId); Assert.That(result, Is.InstanceOf()); var okResult = result as OkObjectResult; Assert.That(okResult?.Value.ToString(), Does.Contain("Friend request sent")); } [Test] public async Task SendRequest_Throws_InvalidOperationException_ReturnsUnprocessableEntity() { var targetUserId = Guid.NewGuid(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()).Returns(targetUserId); _friendsServiceMock.Setup(f => f.SendFriendRequestAsync(targetUserId, targetUserId)) .ThrowsAsync(new InvalidOperationException()); var result = await _controller.SendRequest(targetUserId); Assert.That(result, Is.InstanceOf()); } [Test] public async Task SendRequest_Throws_RequestAlreadySentException_ReturnsConflict() { var targetUserId = Guid.NewGuid(); var currentUserId = Guid.NewGuid(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()).Returns(currentUserId); _friendsServiceMock.Setup(f => f.SendFriendRequestAsync(targetUserId, currentUserId)) .ThrowsAsync(new RequestAlreadySentException(currentUserId, targetUserId)); var result = await _controller.SendRequest(targetUserId); Assert.That(result, Is.InstanceOf()); } [Test] public async Task SendRequest_StatusCode500_IfThrowsSomeException() { // Arrange _friendsServiceMock.Setup(f => f.SendFriendRequestAsync(It.IsAny(), It.IsAny())) .ThrowsAsync(new Exception(_fixture.Create())); // Act var result = await _controller.Search(_fixture.Create()); // Assert Assert.That(result, Is.InstanceOf()); var objectResult = result as ObjectResult; Assert.That(objectResult.StatusCode, Is.EqualTo(500)); } // Tests for GetIncomingRequests action [Test] public async Task GetIncomingRequests_ValidRequest_ReturnsOkResult() { // Arrange var currentId = _fixture.Create(); var friendships = _fixture.CreateMany().ToList(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()) .Returns(currentId); _friendsServiceMock.Setup(f => f.GetIncomingRequestsAsync(currentId)) .ReturnsAsync(friendships); // Act var result = await _controller.GetIncomingRequests(); // Assert Assert.That(result, Is.InstanceOf()); var okResult = result as OkObjectResult; List value = okResult.Value as List; Assert.That(value, Is.Not.Null); Assert.That(value.Count, Is.EqualTo(friendships.Count)); } [Test] public async Task GetIncomingRequests_Throws_InvalidOperationException_ReturnsBadRequest() { // Arrange var currentId = _fixture.Create(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()) .Returns(currentId); _friendsServiceMock.Setup(f => f.GetIncomingRequestsAsync(currentId)) .ThrowsAsync(new InvalidOperationException()); // Act var result = await _controller.GetIncomingRequests(); // Assert Assert.That(result, Is.InstanceOf()); var badRequestResult = result as BadRequestObjectResult; dynamic value = badRequestResult.Value; Assert.That(value, Is.EqualTo("Failed to get friend requests. User data missing.")); } [Test] public async Task GetIncomingRequest_StatusCode500_IfThrowsSomeException() { // Arrange var currentId = _fixture.Create(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()) .Returns(currentId); _friendsServiceMock.Setup(f => f.GetIncomingRequestsAsync(currentId)) .ThrowsAsync(new Exception()); // Act var result = await _controller.GetIncomingRequests(); // Assert Assert.That(result, Is.InstanceOf()); var objectResult = result as ObjectResult; Assert.That(objectResult.StatusCode, Is.EqualTo(500)); } // Tests for AcceptFriend action [Test] public async Task AcceptFriend_ValidRequest_ReturnsOkResult() { // Arrange var currentId = Guid.NewGuid(); var targetUserId = Guid.NewGuid(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()) .Returns(currentId); // Act var result = await _controller.AcceptFriend(targetUserId); // Assert Assert.That(result, Is.InstanceOf()); } [Test] public async Task AcceptFriend_InvalidOperationException_ReturnsNotFound() { // Arrange var currentId = Guid.NewGuid(); var targetUserId = Guid.NewGuid(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()) .Returns(currentId); _friendsServiceMock.Setup(f => f.AcceptFriendRequestAsync(targetUserId, currentId)) .ThrowsAsync(new InvalidOperationException()); // Act var result = await _controller.AcceptFriend(targetUserId); // Assert Assert.That(result, Is.InstanceOf()); } [Test] public async Task AcceptFriend_UnauthorizedAccessException_ReturnsForbid() { // Arrange var currentId = Guid.NewGuid(); var targetUserId = Guid.NewGuid(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()) .Returns(currentId); _friendsServiceMock.Setup(f => f.AcceptFriendRequestAsync(targetUserId, currentId)) .ThrowsAsync(new UnauthorizedAccessException()); // Act var result = await _controller.AcceptFriend(targetUserId); // Assert Assert.That(result, Is.InstanceOf()); } [Test] public async Task AcceptFriend_Exception_ReturnsStatusCode500() { // Arrange var currentId = Guid.NewGuid(); var targetUserId = Guid.NewGuid(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()) .Returns(currentId); _friendsServiceMock.Setup(f => f.AcceptFriendRequestAsync(targetUserId, currentId)) .ThrowsAsync(new Exception()); // Act var result = await _controller.AcceptFriend(targetUserId); // Assert Assert.That(result, Is.InstanceOf()); var objectResult = result as ObjectResult; Assert.That(objectResult.StatusCode, Is.EqualTo(500)); } // Tests for GetFriends action [Test] public async Task GetFriends_ValidRequest_ReturnsOkResult() { // Arrange var currentId = _fixture.Create(); var users = _fixture.CreateMany().ToList(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()) .Returns(currentId); _friendsServiceMock.Setup(f => f.GetFriendsAsync(currentId)) .ReturnsAsync(users); // Act var result = await _controller.GetFriends(); // Assert Assert.That(result, Is.InstanceOf()); var okResult = result as OkObjectResult; List value = okResult.Value as List; Assert.That(value, Is.Not.Null); Assert.That(value.Count, Is.EqualTo(users.Count)); } [Test] public async Task GetFriends_InvalidOperationException_ReturnsBadRequest() { // Arrange var currentId = _fixture.Create(); var users = _fixture.CreateMany().ToList(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()) .Returns(currentId); _friendsServiceMock.Setup(f => f.GetFriendsAsync(currentId)) .ThrowsAsync(new InvalidOperationException()); // Act var result = await _controller.GetFriends(); // Assert Assert.That(result, Is.InstanceOf()); } [Test] public async Task GetFriends_Exception_ReturnsStatusCode500() { // Arrange var currentId = _fixture.Create(); var users = _fixture.CreateMany().ToList(); _currentUserServiceMock.Setup(c => c.GetCurrentUserId()) .Returns(currentId); _friendsServiceMock.Setup(f => f.GetFriendsAsync(currentId)) .ThrowsAsync(new Exception()); // Act var result = await _controller.GetFriends(); // Assert Assert.That(result, Is.InstanceOf()); var objectResult = result as ObjectResult; Assert.That(objectResult.StatusCode, Is.EqualTo(500)); } [TearDown] public void TearDown() { _controller.Dispose(); } }