using FluentAssertions; using Marathon.Domain.Entities; using Marathon.Domain.Enums; using Marathon.Domain.ValueObjects; namespace Marathon.Domain.Tests.Entities; public sealed class OddsSnapshotTests { private static readonly EventId SampleEventId = new("26456117"); private static readonly DateTimeOffset SampleCapturedAt = DateTimeOffset.UtcNow; private static readonly IReadOnlyList OneBet = [ new Bet(MatchScope.Instance, BetType.Win, Side.Side1, null, new OddsRate(1.85m)), ]; [Fact] public void Constructor_CreatesInstance_WhenBetsIsNonEmpty() { var snapshot = new OddsSnapshot(SampleEventId, SampleCapturedAt, OddsSource.PreMatch, OneBet); snapshot.EventId.Should().Be(SampleEventId); snapshot.Bets.Should().HaveCount(1); } [Fact] public void Constructor_ThrowsArgumentException_WhenBetsIsEmpty() { var act = () => new OddsSnapshot(SampleEventId, SampleCapturedAt, OddsSource.PreMatch, []); act.Should().Throw() .WithParameterName("bets"); } [Fact] public void Constructor_ThrowsArgumentNullException_WhenEventIdIsNull() { var act = () => new OddsSnapshot(null!, SampleCapturedAt, OddsSource.PreMatch, OneBet); act.Should().Throw() .WithParameterName("eventId"); } [Fact] public void Constructor_ThrowsArgumentNullException_WhenBetsIsNull() { var act = () => new OddsSnapshot(SampleEventId, SampleCapturedAt, OddsSource.PreMatch, null!); act.Should().Throw() .WithParameterName("bets"); } [Fact] public void OddsSnapshot_IsImmutable_NoSettablePublicProperties() { var snapshotType = typeof(OddsSnapshot); var settableProperties = snapshotType.GetProperties() .Where(p => p.CanWrite && p.GetSetMethod(nonPublic: false) is not null) .ToList(); settableProperties.Should().BeEmpty("OddsSnapshot must be immutable."); } }