namespace TaxBaik.Application.Tests; using TaxBaik.Application.DTOs; using TaxBaik.Application.Services; using TaxBaik.Domain.Entities; using TaxBaik.Domain.Interfaces; using Microsoft.Extensions.Caching.Memory; using Xunit; public class BlogServiceTests { [Fact] public async Task CreateAsync_WhenPublishedWithoutSeoTitle_ThrowsValidationException() { var service = new BlogService(new FakeBlogPostRepository(), new MemoryCache(new MemoryCacheOptions())); await Assert.ThrowsAsync(() => service.CreateAsync(new CreateBlogPostDto { Title = "테스트 포스트", Content = "본문", SeoDescription = "설명", IsPublished = true })); } [Fact] public async Task CreateAsync_WhenTitleDuplicates_GeneratesUniqueSlug() { var repository = new FakeBlogPostRepository { Posts = [ new BlogPost { Id = 1, Title = "같은 제목", Content = "본문", Slug = "같은-제목" } ] }; var service = new BlogService(repository, new MemoryCache(new MemoryCacheOptions())); var post = await service.CreateAsync(new CreateBlogPostDto { Title = "같은 제목", Content = "본문" }); Assert.Equal("같은-제목-2", post.Slug); } private sealed class FakeBlogPostRepository : IBlogPostRepository { public List Posts { get; init; } = []; public Task GetByIdAsync(int id, CancellationToken cancellationToken = default) => Task.FromResult(Posts.FirstOrDefault(x => x.Id == id)); public Task GetBySlugAsync(string slug, CancellationToken cancellationToken = default) => Task.FromResult(Posts.FirstOrDefault(x => x.Slug == slug && x.IsPublished)); public Task<(IEnumerable Items, int Total)> GetPublishedPagedAsync( int page, int pageSize, int? categoryId = null, CancellationToken cancellationToken = default) { var items = Posts.Where(x => x.IsPublished).ToList(); return Task.FromResult<(IEnumerable, int)>((items, items.Count)); } public Task> GetByCategorySlugAsync(string categorySlug, int limit, CancellationToken cancellationToken = default) => Task.FromResult>(Posts.Where(x => x.IsPublished).Take(limit).ToList()); public Task> GetAllForAdminAsync(CancellationToken cancellationToken = default) => Task.FromResult>(Posts); public Task<(IEnumerable Items, int Total)> GetAdminPagedAsync( int page, int pageSize, CancellationToken cancellationToken = default) { var items = Posts.ToList(); return Task.FromResult<(IEnumerable, int)>((items, items.Count)); } public Task CreateAsync(BlogPost post, CancellationToken cancellationToken = default) { post.Id = Posts.Count + 1; Posts.Add(post); return Task.FromResult(post.Id); } public Task UpdateAsync(BlogPost post, CancellationToken cancellationToken = default) => Task.CompletedTask; public Task DeleteAsync(int id, CancellationToken cancellationToken = default) => Task.CompletedTask; public Task IncrementViewCountAsync(int id, CancellationToken cancellationToken = default) => Task.CompletedTask; } }