using Novelly.Api.Chapters; using Novelly.Api.Common; using Novelly.Api.Common.Validation; using Novelly.Api.Projects; namespace Novelly.Api.Tests; /// /// Covers the exception-handling rework: a missing entity is an ordinary result, not a /// thrown exception; rejects missing required arguments; and a /// service re-validates a request even when a direct caller skips the API's own filter. /// [TestFixture] public class ExceptionHandlingTests : ServiceTestFixture { [Test] public void Guard_rejects_an_empty_guid_passed_as_a_required_id() => Assert.That(() => Projects.GetAsync(Guid.Empty), Throws.TypeOf()); [Test] public void Guard_rejects_a_null_request_object() => Assert.That( () => Projects.CreateAsync(null!), Throws.TypeOf()); [Test] public async Task Deleting_a_missing_project_returns_false_rather_than_throwing() => Assert.That(await Projects.DeleteAsync(Guid.NewGuid()), Is.False); [Test] public void A_blank_title_fails_the_create_project_validator() { var result = new CreateProjectRequestValidator().Validate(new CreateProjectRequest("")); Assert.Multiple(() => { Assert.That(result.IsInvalid, Is.True); Assert.That(result.Errors.Select(e => e.PropertyName), Has.Member("Title")); }); } [Test] public void Calling_a_service_directly_with_an_invalid_request_throws_rather_than_silently_accepting_it() => Assert.That( () => Projects.CreateAsync(new CreateProjectRequest("")), Throws.TypeOf()); [Test] public async Task Creating_a_chapter_under_a_missing_project_returns_null_rather_than_throwing() => Assert.That(await Chapters.CreateAsync(Guid.NewGuid(), new CreateChapterRequest("Landfall")), Is.Null); }