Добавлены тесты
This commit is contained in:
mfnefd 2024-12-09 19:57:29 +04:00
commit 486645fc46
10 changed files with 619 additions and 2 deletions

View File

@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contracts", "Contracts\Cont
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "Infrastructure\Infrastructure.csproj", "{A35121D4-7D41-4266-8DA4-87135E8ABF89}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Services.Tests", "Services.Tests\Services.Tests.csproj", "{F0BDEEB0-2850-4733-B196-DBC677B35E47}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -36,5 +38,9 @@ Global
{A35121D4-7D41-4266-8DA4-87135E8ABF89}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A35121D4-7D41-4266-8DA4-87135E8ABF89}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A35121D4-7D41-4266-8DA4-87135E8ABF89}.Release|Any CPU.Build.0 = Release|Any CPU
{F0BDEEB0-2850-4733-B196-DBC677B35E47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0BDEEB0-2850-4733-B196-DBC677B35E47}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0BDEEB0-2850-4733-B196-DBC677B35E47}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F0BDEEB0-2850-4733-B196-DBC677B35E47}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,83 @@
using Contracts.DTO;
using Contracts.Repositories;
using Contracts.SearchModels;
using Contracts.ViewModels;
using Moq;
using Services.Domain;
using Services.Support.Exceptions;
namespace Services.Tests.Domain;
public class AuthServiceTests
{
[Fact]
public void Register_WhenUserExists_ThrowsAlreadyExistsException()
{
var userRepoMock = new Mock<IUserRepo>();
userRepoMock.Setup(repo => repo.Get(It.IsAny<UserSearch>()))
.ReturnsAsync(new UserDto());
var authService = new AuthService(userRepoMock.Object);
var user = new UserDto { Name = "John Doe", Password = "password" };
Assert.ThrowsAsync<AlreadyExistsException>(() => authService.Register(user));
}
[Fact]
public void Register_WhenUserDoesNotExist_ThenCreateUser_ReturnsUserViewModel()
{
var userRepoMock = new Mock<IUserRepo>();
userRepoMock.Setup(repo => repo.Get(It.IsAny<UserSearch>())).ReturnsAsync((UserDto)null);
userRepoMock.Setup(repo => repo.Create(It.IsAny<UserDto>())).ReturnsAsync(new UserDto());
var authService = new AuthService(userRepoMock.Object);
var user = new UserDto { Name = "John Doe", Password = "password" };
var result = authService.Register(user);
userRepoMock.Verify(repo => repo.Create(It.IsAny<UserDto>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<Task<UserViewModel>>(result);
}
[Fact]
public void Login_WhenUserDoesNotExist_ThrowsUserNotFoundException()
{
var userRepoMock = new Mock<IUserRepo>();
userRepoMock.Setup(repo => repo.Get(It.IsAny<UserSearch>())).ReturnsAsync((UserDto)null);
var authService = new AuthService(userRepoMock.Object);
var user = new UserLoginDto { Name = "John Doe", Password = "password" };
Assert.ThrowsAsync<UserNotFoundException>(() => authService.Login(user));
}
[Fact]
public void Login_WhenUserExists_ReturnsUserViewModel()
{
var userRepoMock = new Mock<IUserRepo>();
userRepoMock.Setup(repo => repo.Get(It.IsAny<UserSearch>())).ReturnsAsync(new UserDto());
var authService = new AuthService(userRepoMock.Object);
var user = new UserLoginDto { Name = "John Doe", Password = "password" };
var result = authService.Login(user);
userRepoMock.Verify(repo => repo.Get(It.IsAny<UserSearch>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<Task<UserViewModel>>(result);
}
[Fact]
public void Login_WhenWrongLoginData_ThrowsArgumentException()
{
var userRepoMock = new Mock<IUserRepo>();
userRepoMock.Setup(repo => repo.Get(It.IsAny<UserSearch>())).ReturnsAsync((UserDto)null);
var authService = new AuthService(userRepoMock.Object);
UserLoginDto user1 = null;
UserLoginDto user2 = new() { Name = "", Password = "password" };
UserLoginDto user3 = new() { Name = "John Doe", Password = "" };
UserLoginDto user4 = new() { Name = "", Password = "" };
Assert.ThrowsAsync<ArgumentException>(() => authService.Login(user1));
Assert.ThrowsAsync<ArgumentException>(() => authService.Login(user2));
Assert.ThrowsAsync<ArgumentException>(() => authService.Login(user3));
Assert.ThrowsAsync<ArgumentException>(() => authService.Login(user4));
}
}

View File

@ -0,0 +1,138 @@
using Contracts.DTO;
using Contracts.Repositories;
using Contracts.SearchModels;
using Contracts.ViewModels;
using Moq;
using Services.Domain;
using Services.Support.Exceptions;
using Services.Tests.Support.Fakes.Database;
using Services.Tests.Support.Fakes.Repositories;
namespace Services.Tests.Domain;
public class ChangeRecordServiceTests
{
[Theory]
[InlineData(50)]
[InlineData(-50)]
public async Task Create_WhenUserExists_ThenChangeBalance_ReturnsChangeRecordViewModel(int recordSum, int userBalance = 100)
{
var userRepoFake = new UserRepoFake();
var changeRecordRepoMock = new Mock<IChangeRecordRepo>();
changeRecordRepoMock.Setup(repo => repo.Create(It.IsAny<ChangeRecordDto>())).ReturnsAsync(new ChangeRecordDto());
var changeRecordService = new ChangeRecordService(changeRecordRepoMock.Object, userRepoFake);
// Add user
var user = new UserDto() { Id = Guid.NewGuid(), Balance = userBalance };
await userRepoFake.Create(user);
var changeRecord = new ChangeRecordDto { UserId = user.Id, Sum = recordSum, SpendingGroupId = Guid.NewGuid() };
var result = await changeRecordService.Create(changeRecord);
changeRecordRepoMock.Verify(repo => repo.Create(It.IsAny<ChangeRecordDto>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<ChangeRecordViewModel>(result);
var existedUser = await userRepoFake.Get(new UserSearch { Id = user.Id });
Assert.Equal(existedUser.Balance, userBalance + recordSum);
DbFake.ClearDb();
}
[Theory]
[InlineData(50)]
[InlineData(-50)]
public async Task Delete_WhenUserExists_ThenChangeBalance_ReturnsChangeRecordViewModel(int recordSum, int userBalance = 100)
{
var user = new UserDto() { Id = Guid.NewGuid(), Balance = userBalance };
var changeRecord = new ChangeRecordDto { UserId = user.Id, Sum = recordSum, SpendingGroupId = Guid.NewGuid() };
var userRepoFake = new UserRepoFake();
var changeRecordRepoMock = new Mock<IChangeRecordRepo>();
changeRecordRepoMock.Setup(repo => repo.Delete(It.IsAny<ChangeRecordSearch>())).ReturnsAsync(changeRecord);
changeRecordRepoMock.Setup(repo => repo.Create(It.IsAny<ChangeRecordDto>())).ReturnsAsync(new ChangeRecordDto());
var changeRecordService = new ChangeRecordService(changeRecordRepoMock.Object, userRepoFake);
// Add user and record
await userRepoFake.Create(user);
await changeRecordService.Create(changeRecord);
var result = await changeRecordService.Delete(new ChangeRecordSearch { Id = changeRecord.Id });
changeRecordRepoMock.Verify(repo => repo.Delete(It.IsAny<ChangeRecordSearch>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<ChangeRecordViewModel>(result);
var existedUser = await userRepoFake.Get(new UserSearch { Id = user.Id });
Assert.Equal(existedUser.Balance, userBalance);
DbFake.ClearDb();
}
[Fact]
public void Delete_WhenRecordNotFound_ThenThrowsEntityNotFoundException()
{
var changeRecordRepoMock = new Mock<IChangeRecordRepo>();
var userRepoMock = new Mock<IUserRepo>();
changeRecordRepoMock.Setup(repo => repo.Delete(It.IsAny<ChangeRecordSearch>())).ReturnsAsync((ChangeRecordDto)null);
var changeRecordService = new ChangeRecordService(changeRecordRepoMock.Object, userRepoMock.Object);
Assert.ThrowsAsync<EntityNotFoundException>(() => changeRecordService.Delete(new()));
}
[Fact]
public async Task GetList_ReturnsChangeRecordViewModels()
{
var changeRecordRepoMock = new Mock<IChangeRecordRepo>();
var userRepoMock = new Mock<IUserRepo>();
changeRecordRepoMock.Setup(repo => repo.GetList(It.IsAny<ChangeRecordSearch>())).ReturnsAsync(GetAllChangeRecords());
var changeRecordService = new ChangeRecordService(changeRecordRepoMock.Object, userRepoMock.Object);
var result = await changeRecordService.GetList();
changeRecordRepoMock.Verify(repo => repo.GetList(It.IsAny<ChangeRecordSearch>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<List<ChangeRecordViewModel>>(result.ToList());
}
[Theory]
[InlineData(50, 25)]
[InlineData(-50, 25)]
public async Task Update_WhenUserExists_ThenChangeBalance_ReturnsChangeRecordViewModel(int recordSum, int recorNewSum, int userBalance = 100)
{
var user = new UserDto() { Id = Guid.NewGuid(), Balance = userBalance };
var changeRecord = new ChangeRecordDto { UserId = user.Id, Sum = recordSum, SpendingGroupId = Guid.NewGuid() };
var userRepoFake = new UserRepoFake();
var changeRecordRepoMock = new Mock<IChangeRecordRepo>();
changeRecordRepoMock.Setup(repo => repo.Update(It.IsAny<ChangeRecordDto>())).ReturnsAsync(changeRecord);
changeRecordRepoMock.Setup(repo => repo.Create(It.IsAny<ChangeRecordDto>())).ReturnsAsync(new ChangeRecordDto());
var changeRecordService = new ChangeRecordService(changeRecordRepoMock.Object, userRepoFake);
// Add user and record
await userRepoFake.Create(user);
await changeRecordService.Create(changeRecord);
var newChangeRecord = new ChangeRecordDto { Id = Guid.NewGuid(), UserId = user.Id, Sum = recorNewSum, SpendingGroupId = Guid.NewGuid() };
var result = await changeRecordService.Update(newChangeRecord);
changeRecordRepoMock.Verify(repo => repo.Update(It.IsAny<ChangeRecordDto>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<ChangeRecordViewModel>(result);
var existedUser = await userRepoFake.Get(new UserSearch { Id = user.Id });
Assert.Equal(existedUser.Balance, userBalance + recorNewSum);
DbFake.ClearDb();
}
[Fact]
public void Update_WhenRecordNotExists_ThenThrowsEntityNotFoundException()
{
var changeRecordRepoMock = new Mock<IChangeRecordRepo>();
changeRecordRepoMock.Setup(repo => repo.Update(It.IsAny<ChangeRecordDto>())).ReturnsAsync((ChangeRecordDto?)null);
var userRepoMock = new Mock<IUserRepo>();
var changeRecordService = new ChangeRecordService(changeRecordRepoMock.Object, userRepoMock.Object);
var changeRecord = new ChangeRecordDto { Id = Guid.NewGuid(), UserId = Guid.NewGuid(), Sum = 50, SpendingGroupId = Guid.NewGuid() };
Assert.ThrowsAsync<EntityNotFoundException>(() => changeRecordService.Update(changeRecord));
}
public IEnumerable<ChangeRecordDto> GetAllChangeRecords() => new List<ChangeRecordDto>()
{
new ChangeRecordDto() { Id = Guid.NewGuid(), Sum = 50, SpendingGroupId = Guid.NewGuid(), UserId = Guid.NewGuid() },
new ChangeRecordDto() { Id = Guid.NewGuid(), Sum = 50, SpendingGroupId = Guid.NewGuid(), UserId = Guid.NewGuid() },
};
}

View File

@ -0,0 +1,118 @@
using Contracts.DTO;
using Contracts.Repositories;
using Contracts.SearchModels;
using Contracts.Services;
using Contracts.ViewModels;
using Moq;
using Services.Support.Exceptions;
namespace Services.Tests.Domain;
public class SpendingGroupServiceTests
{
[Fact]
public async Task Create_ReturnsSpendingGroupViewModel()
{
var spendingGroupRepoMock = new Mock<ISpendingGroupRepo>();
spendingGroupRepoMock.Setup(repo => repo.Create(It.IsAny<SpendingGroupDto>())).ReturnsAsync(new SpendingGroupDto());
var spendingGroupService = new SpendingGroupService(spendingGroupRepoMock.Object);
var result = await spendingGroupService.Create(new());
spendingGroupRepoMock.Verify(repo => repo.Create(It.IsAny<SpendingGroupDto>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<SpendingGroupViewModel>(result);
}
[Fact]
public async Task GetList_ReturnsSpendingGroupViewModels()
{
var spendingGroupRepoMock = new Mock<ISpendingGroupRepo>();
spendingGroupRepoMock.Setup(repo => repo.GetList(It.IsAny<SpendingGroupSearch>())).ReturnsAsync(_getAllSpendingGroups());
var spendingGroupService = new SpendingGroupService(spendingGroupRepoMock.Object);
var result = await spendingGroupService.GetList();
spendingGroupRepoMock.Verify(repo => repo.GetList(It.IsAny<SpendingGroupSearch>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<List<SpendingGroupViewModel>>(result.ToList());
}
[Fact]
public async Task Delete_ReturnsSpendingGroupViewModel()
{
var spendingGroupRepoMock = new Mock<ISpendingGroupRepo>();
spendingGroupRepoMock.Setup(repo => repo.Delete(It.IsAny<SpendingGroupSearch>())).ReturnsAsync(new SpendingGroupDto());
var spendingGroupService = new SpendingGroupService(spendingGroupRepoMock.Object);
var result = await spendingGroupService.Delete(new());
spendingGroupRepoMock.Verify(repo => repo.Delete(It.IsAny<SpendingGroupSearch>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<SpendingGroupViewModel>(result);
}
[Fact]
public void Delete_WhenSpendingGroupNotFound_ThrowsEntityNotFoundException()
{
var spendingGroupRepoMock = new Mock<ISpendingGroupRepo>();
spendingGroupRepoMock.Setup(repo => repo.Delete(It.IsAny<SpendingGroupSearch>())).ReturnsAsync((SpendingGroupDto)null);
var spendingGroupService = new SpendingGroupService(spendingGroupRepoMock.Object);
Assert.ThrowsAsync<EntityNotFoundException>(() => spendingGroupService.Delete(new()));
}
[Fact]
public async Task Update_ReturnsSpendingGroupViewModel()
{
var spendingGroupRepoMock = new Mock<ISpendingGroupRepo>();
spendingGroupRepoMock.Setup(repo => repo.Update(It.IsAny<SpendingGroupDto>())).ReturnsAsync(new SpendingGroupDto());
var spendingGroupService = new SpendingGroupService(spendingGroupRepoMock.Object);
var result = await spendingGroupService.Update(new());
spendingGroupRepoMock.Verify(repo => repo.Update(It.IsAny<SpendingGroupDto>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<SpendingGroupViewModel>(result);
}
[Fact]
public void Update_WhenSpendingGroupNotFound_ThrowsEntityNotFoundException()
{
var spendingGroupRepoMock = new Mock<ISpendingGroupRepo>();
spendingGroupRepoMock.Setup(repo => repo.Update(It.IsAny<SpendingGroupDto>())).ReturnsAsync((SpendingGroupDto)null);
var spendingGroupService = new SpendingGroupService(spendingGroupRepoMock.Object);
Assert.ThrowsAsync<EntityNotFoundException>(() => spendingGroupService.Update(new()));
}
[Fact]
public async Task GetDetails_ReturnsSpendingGroupViewModel()
{
var spendingGroupRepoMock = new Mock<ISpendingGroupRepo>();
spendingGroupRepoMock.Setup(repo => repo.Get(It.IsAny<SpendingGroupSearch>())).ReturnsAsync(new SpendingGroupDto());
var spendingGroupService = new SpendingGroupService(spendingGroupRepoMock.Object);
var result = await spendingGroupService.GetDetails(new());
spendingGroupRepoMock.Verify(repo => repo.Get(It.IsAny<SpendingGroupSearch>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<SpendingGroupViewModel>(result);
}
[Fact]
public void GetDetails_WhenSpendingGroupNotFound_ThrowsEntityNotFoundException()
{
var spendingGroupRepoMock = new Mock<ISpendingGroupRepo>();
spendingGroupRepoMock.Setup(repo => repo.Get(It.IsAny<SpendingGroupSearch>())).ReturnsAsync((SpendingGroupDto)null);
var spendingGroupService = new SpendingGroupService(spendingGroupRepoMock.Object);
Assert.ThrowsAsync<EntityNotFoundException>(() => spendingGroupService.GetDetails(new()));
}
private IEnumerable<SpendingGroupDto> _getAllSpendingGroups() => new List<SpendingGroupDto>()
{
new() { Id = Guid.NewGuid(), Name = "Group 1" },
new() { Id = Guid.NewGuid(), Name = "Group 2" }
};
}

View File

@ -0,0 +1,101 @@
using Contracts.DTO;
using Contracts.Repositories;
using Contracts.SearchModels;
using Contracts.ViewModels;
using Moq;
using Services.Domain;
using Services.Support.Exceptions;
namespace Services.Tests.Domain;
public class SpendingPlanServiceTests
{
[Fact]
public async Task Create_ReturnsSpendingPlanViewModel()
{
var spendingPlanRepoMock = new Mock<ISpendingPlanRepo>();
spendingPlanRepoMock.Setup(repo => repo.Create(It.IsAny<SpendingPlanDto>())).ReturnsAsync(new SpendingPlanDto());
var spendingPlanService = new SpendingPlanService(spendingPlanRepoMock.Object);
var result = await spendingPlanService.Create(new());
spendingPlanRepoMock.Verify(repo => repo.Create(It.IsAny<SpendingPlanDto>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<SpendingPlanViewModel>(result);
}
[Fact]
public async Task Update_WhenPlanExists_ThenUpdatePlan_ReturnsSpendingPlanViewModel()
{
var spendingPlanRepoMock = new Mock<ISpendingPlanRepo>();
spendingPlanRepoMock.Setup(repo => repo.Update(It.IsAny<SpendingPlanDto>()))
.ReturnsAsync(new SpendingPlanDto());
var spendingPlanService = new SpendingPlanService(spendingPlanRepoMock.Object);
var result = await spendingPlanService.Update(new());
spendingPlanRepoMock.Verify(repo => repo.Update(It.IsAny<SpendingPlanDto>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<SpendingPlanViewModel>(result);
}
[Fact]
public async Task Update_WhenPlanNotFound_ThenThrowsEntityNotFoundException()
{
var spendingPlanRepoMock = new Mock<ISpendingPlanRepo>();
spendingPlanRepoMock.Setup(repo => repo.Update(It.IsAny<SpendingPlanDto>()))
.ReturnsAsync((SpendingPlanDto)null);
var spendingPlanService = new SpendingPlanService(spendingPlanRepoMock.Object);
await Assert.ThrowsAsync<EntityNotFoundException>(() => spendingPlanService.Update(new()));
}
[Fact]
public async Task Delete_WhenPlanExists_ThenDeletePlan_ReturnsSpendingPlanViewModel()
{
var spendingPlanRepoMock = new Mock<ISpendingPlanRepo>();
spendingPlanRepoMock.Setup(repo => repo.Delete(It.IsAny<SpendingPlanSearch>()))
.ReturnsAsync(new SpendingPlanDto());
var spendingPlanService = new SpendingPlanService(spendingPlanRepoMock.Object);
var result = await spendingPlanService.Delete(new());
spendingPlanRepoMock.Verify(repo => repo.Delete(It.IsAny<SpendingPlanSearch>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<SpendingPlanViewModel>(result);
}
[Fact]
public async Task Delete_WhenPlanNotFound_ThenThrowsEntityNotFoundException()
{
var spendingPlanRepoMock = new Mock<ISpendingPlanRepo>();
spendingPlanRepoMock.Setup(repo => repo.Delete(It.IsAny<SpendingPlanSearch>()))
.ReturnsAsync((SpendingPlanDto)null);
var spendingPlanService = new SpendingPlanService(spendingPlanRepoMock.Object);
await Assert.ThrowsAsync<EntityNotFoundException>(() => spendingPlanService.Delete(new()));
}
[Fact]
public async Task GetList_ReturnsSpendingPlanViewModels()
{
var spendingPlanRepoMock = new Mock<ISpendingPlanRepo>();
spendingPlanRepoMock.Setup(repo => repo.GetList(It.IsAny<SpendingPlanSearch>()))
.ReturnsAsync(_getAllSpendingPlans());
var spendingPlanService = new SpendingPlanService(spendingPlanRepoMock.Object);
var result = await spendingPlanService.GetList(new());
spendingPlanRepoMock.Verify(repo => repo.GetList(It.IsAny<SpendingPlanSearch>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<List<SpendingPlanViewModel>>(result.ToList());
Assert.Equal(2, result.Count());
}
private IEnumerable<SpendingPlanDto> _getAllSpendingPlans() => new List<SpendingPlanDto>()
{
new() { Id = Guid.NewGuid(), StartAt = DateTime.Now, EndAt = DateTime.Now, Sum = 100 },
new() { Id = Guid.NewGuid(), StartAt = DateTime.Now, EndAt = DateTime.Now, Sum = 200 }
};
}

View File

@ -0,0 +1,74 @@
using Contracts.DTO;
using Contracts.Repositories;
using Contracts.SearchModels;
using Contracts.ViewModels;
using Moq;
using Services.Domain;
using Services.Support.Exceptions;
namespace Services.Tests.Domain;
public class UserServiceTests
{
[Fact]
public async Task Delete_WhenUserExists_ThenDeleteUser_ReturnsUserViewModel()
{
var userRepoMock = new Mock<IUserRepo>();
userRepoMock.Setup(repo => repo.Delete(It.IsAny<UserSearch>())).ReturnsAsync(new UserDto());
var userService = new UserService(userRepoMock.Object);
var result = await userService.Delete(new UserSearch());
userRepoMock.Verify(repo => repo.Delete(It.IsAny<UserSearch>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<UserViewModel>(result);
}
[Fact]
public void Delete_WhenUserNotExists_ThenThrowsUserNotFoundException()
{
var userRepoMock = new Mock<IUserRepo>();
userRepoMock.Setup(repo => repo.Delete(It.IsAny<UserSearch>())).ReturnsAsync((UserDto?)null);
var userService = new UserService(userRepoMock.Object);
Assert.ThrowsAsync<UserNotFoundException>(() => userService.Delete(new UserSearch()));
}
[Fact]
public async Task Update_WhenUserExists_ThenUpdateUser_ReturnsUserViewModel()
{
var userRepoMock = new Mock<IUserRepo>();
userRepoMock.Setup(repo => repo.Update(It.IsAny<UserDto>())).ReturnsAsync(new UserDto());
var userService = new UserService(userRepoMock.Object);
var result = await userService.UpdateUserData(new UserDto());
userRepoMock.Verify(repo => repo.Update(It.IsAny<UserDto>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<UserViewModel>(result);
}
[Fact]
public void Update_WhenUserNotFound_ThenThrowsUserNotFoundException()
{
var userRepoMock = new Mock<IUserRepo>();
userRepoMock.Setup(repo => repo.Update(It.IsAny<UserDto>())).ReturnsAsync((UserDto?)null);
var userService = new UserService(userRepoMock.Object);
Assert.ThrowsAsync<UserNotFoundException>(() => userService.UpdateUserData(new UserDto()));
}
[Fact]
public async Task GetDetails_ReturnsUserViewModel()
{
var userRepoMock = new Mock<IUserRepo>();
userRepoMock.Setup(repo => repo.Get(It.IsAny<UserSearch>())).ReturnsAsync(new UserDto());
var userService = new UserService(userRepoMock.Object);
var result = await userService.GetDetails(new UserSearch());
userRepoMock.Verify(repo => repo.Get(It.IsAny<UserSearch>()), Times.Once);
Assert.NotNull(result);
Assert.IsType<UserViewModel>(result);
}
}

View File

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="moq" Version="4.20.72" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Services\Services.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,13 @@
using Contracts.DTO;
namespace Services.Tests.Support.Fakes.Database;
internal static class DbFake
{
public static List<UserDto> Users = new();
public static void ClearDb()
{
Users.Clear();
}
}

View File

@ -0,0 +1,55 @@
using System.Data.Common;
using Contracts.DTO;
using Contracts.Repositories;
using Contracts.SearchModels;
using Services.Tests.Support.Fakes.Database;
namespace Services.Tests.Support.Fakes.Repositories;
internal class UserRepoFake : IUserRepo
{
public async Task<bool> ChangeBalance(UserSearch search, decimal amount)
{
var user = DbFake.Users.FirstOrDefault(u => u.Id == search.Id);
if (user != null)
{
user.Balance += amount;
return await Task.FromResult(true);
}
return await Task.FromResult(false);
}
public async Task<UserDto> Create(UserDto user)
{
DbFake.Users.Add(user);
return await Task.FromResult(user);
}
public async Task<UserDto?> Delete(UserSearch search)
{
var user = DbFake.Users.FirstOrDefault(u => u.Id == search.Id);
if (user != null)
{
DbFake.Users.Remove(user);
}
return await Task.FromResult(user);
}
public async Task<UserDto?> Get(UserSearch search)
{
return await Task.FromResult(DbFake.Users.FirstOrDefault(u => u.Id == search.Id));
}
public async Task<UserDto?> Update(UserDto user)
{
var existingUser = DbFake.Users.FirstOrDefault(u => u.Id == user.Id);
if (existingUser != null)
{
existingUser.Name = user.Name;
existingUser.Password = user.Password;
DbFake.Users.Remove(existingUser);
DbFake.Users.Add(existingUser);
}
return await Task.FromResult(existingUser);
}
}

View File

@ -4,6 +4,7 @@ using Contracts.Repositories;
using Contracts.SearchModels;
using Contracts.Services;
using Contracts.ViewModels;
using Services.Support.Exceptions;
namespace Services.Domain;
@ -32,7 +33,7 @@ public class ChangeRecordService : IChangeRecordService
var record = await _changeRecordRepo.Delete(search);
if (record == null)
{
throw new EntryPointNotFoundException("При удалении не получилось найти запись измнения баланса");
throw new EntityNotFoundException("При удалении не получилось найти запись измнения баланса");
}
// Возвращает баланс обратно
await _userRepo.ChangeBalance(new() { Id = record.UserId }, -record.Sum);
@ -51,7 +52,7 @@ public class ChangeRecordService : IChangeRecordService
var record = await _changeRecordRepo.Update(model);
if (record == null)
{
throw new EntryPointNotFoundException("При изменении не получилось найти запись измнения баланса");
throw new EntityNotFoundException("При изменении не получилось найти запись измнения баланса");
}
await _userRepo.ChangeBalance(new() { Id = model.UserId }, model.Sum - record.Sum);
return record.ToView();