feat: добавил новые юнит-тесты для сервисов и маппинга
Backend CI / build-and-test (push) Successful in 48s
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Successful in 5s
🚀 Create and publish a Docker image / Build & publish backend image (push) Successful in 24s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Failing after 14s
🚀 Create and publish a Docker image / Update stack on Portainer (push) Successful in 2s
Backend CI / build-and-test (push) Successful in 48s
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Successful in 5s
🚀 Create and publish a Docker image / Build & publish backend image (push) Successful in 24s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Failing after 14s
🚀 Create and publish a Docker image / Update stack on Portainer (push) Successful in 2s
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using UniVerse.Application.DTOs.Courses;
|
||||
using UniVerse.Domain.Entities;
|
||||
using UniVerse.Domain.Enums;
|
||||
using UniVerse.Domain.Exceptions;
|
||||
using UniVerse.Infrastructure.Data;
|
||||
using UniVerse.Infrastructure.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace UniVerse.Api.Tests.Courses;
|
||||
|
||||
public class CourseServiceTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task GetAllAsync_AppliesSearchSyncedTagFiltersAndPagination()
|
||||
{
|
||||
await using var db = CreateDbContext();
|
||||
db.Tags.AddRange(
|
||||
new Tag { Id = 1, Name = "Backend", Type = TagType.Subject },
|
||||
new Tag { Id = 2, Name = "Frontend", Type = TagType.Subject });
|
||||
db.Courses.AddRange(
|
||||
Course(1, "ASP.NET Core", true, new DateTime(2026, 1, 3, 0, 0, 0, DateTimeKind.Utc)),
|
||||
Course(2, "Vue Basics", true, new DateTime(2026, 1, 2, 0, 0, 0, DateTimeKind.Utc)),
|
||||
Course(3, "Advanced ASP.NET", false, new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
|
||||
db.CourseTags.AddRange(
|
||||
new CourseTag { CourseId = 1, TagId = 1 },
|
||||
new CourseTag { CourseId = 2, TagId = 2 },
|
||||
new CourseTag { CourseId = 3, TagId = 1 });
|
||||
await db.SaveChangesAsync();
|
||||
var service = new CourseService(db);
|
||||
|
||||
var result = await service.GetAllAsync(new CourseFilterRequest(
|
||||
TagId: 1,
|
||||
Search: "asp",
|
||||
IsSynced: true,
|
||||
Page: 1,
|
||||
PageSize: 10));
|
||||
|
||||
var item = Assert.Single(result.Items);
|
||||
Assert.Equal(1, item.Id);
|
||||
Assert.Equal(1, result.TotalCount);
|
||||
Assert.Equal(1, result.TotalPages);
|
||||
Assert.Equal("Backend", Assert.Single(item.Tags).Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAllAsync_ReturnsRequestedPageMetadata()
|
||||
{
|
||||
await using var db = CreateDbContext();
|
||||
db.Courses.AddRange(
|
||||
Course(1, "Old", false, new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc)),
|
||||
Course(2, "Middle", false, new DateTime(2026, 1, 2, 0, 0, 0, DateTimeKind.Utc)),
|
||||
Course(3, "Newest", false, new DateTime(2026, 1, 3, 0, 0, 0, DateTimeKind.Utc)));
|
||||
await db.SaveChangesAsync();
|
||||
var service = new CourseService(db);
|
||||
|
||||
var result = await service.GetAllAsync(new CourseFilterRequest(null, null, null, Page: 2, PageSize: 1));
|
||||
|
||||
Assert.Equal(3, result.TotalCount);
|
||||
Assert.Equal(2, result.Page);
|
||||
Assert.Equal(1, result.PageSize);
|
||||
Assert.Equal(3, result.TotalPages);
|
||||
Assert.Equal(2, Assert.Single(result.Items).Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddTagAsync_LinksExistingCourseAndTag()
|
||||
{
|
||||
await using var db = CreateDbContext();
|
||||
db.Courses.Add(Course(1, "Course", false, DateTime.UtcNow));
|
||||
db.Tags.Add(new Tag { Id = 10, Name = "Tag", Type = TagType.Topic });
|
||||
await db.SaveChangesAsync();
|
||||
var service = new CourseService(db);
|
||||
|
||||
await service.AddTagAsync(1, 10);
|
||||
|
||||
Assert.True(await db.CourseTags.AnyAsync(ct => ct.CourseId == 1 && ct.TagId == 10));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddTagAsync_ThrowsWhenTagAlreadyLinked()
|
||||
{
|
||||
await using var db = CreateDbContext();
|
||||
db.Courses.Add(Course(1, "Course", false, DateTime.UtcNow));
|
||||
db.Tags.Add(new Tag { Id = 10, Name = "Tag", Type = TagType.Topic });
|
||||
db.CourseTags.Add(new CourseTag { CourseId = 1, TagId = 10 });
|
||||
await db.SaveChangesAsync();
|
||||
var service = new CourseService(db);
|
||||
|
||||
await Assert.ThrowsAsync<ConflictException>(() => service.AddTagAsync(1, 10));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddTagAsync_ThrowsWhenCourseOrTagMissing()
|
||||
{
|
||||
await using var db = CreateDbContext();
|
||||
db.Courses.Add(Course(1, "Course", false, DateTime.UtcNow));
|
||||
db.Tags.Add(new Tag { Id = 10, Name = "Tag", Type = TagType.Topic });
|
||||
await db.SaveChangesAsync();
|
||||
var service = new CourseService(db);
|
||||
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => service.AddTagAsync(404, 10));
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => service.AddTagAsync(1, 404));
|
||||
}
|
||||
|
||||
private static AppDbContext CreateDbContext()
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<AppDbContext>()
|
||||
.UseInMemoryDatabase($"CourseServiceTests_{Guid.NewGuid()}")
|
||||
.Options;
|
||||
return new AppDbContext(options);
|
||||
}
|
||||
|
||||
private static Course Course(int id, string name, bool isSynced, DateTime createdAt) => new()
|
||||
{
|
||||
Id = id,
|
||||
Name = name,
|
||||
IsSynced = isSynced,
|
||||
CreatedAt = createdAt
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user