25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

148 satır
5.7KB

  1. using CartWise.Application.Services;
  2. using CartWise.Domain.Entities;
  3. using CartWise.Domain.Enums;
  4. using CartWise.Infrastructure.Data;
  5. using Microsoft.EntityFrameworkCore;
  6. namespace CartWise.Application.Tests;
  7. public class PriceServiceTests : IDisposable
  8. {
  9. private static readonly DateTime Now = new(2026, 8, 10, 12, 0, 0, DateTimeKind.Utc);
  10. private readonly CartWiseDbContext _db;
  11. private readonly PriceService _sut;
  12. public PriceServiceTests()
  13. {
  14. var options = new DbContextOptionsBuilder<CartWiseDbContext>()
  15. .UseInMemoryDatabase(Guid.NewGuid().ToString())
  16. .Options;
  17. _db = new CartWiseDbContext(options);
  18. _sut = new PriceService(_db, TimeProvider.System);
  19. }
  20. public void Dispose()
  21. {
  22. _db.Dispose();
  23. GC.SuppressFinalize(this);
  24. }
  25. [Fact]
  26. public async Task GetHouseholdPriceInsightAsync_ReturnsNullWhenNoObservationsExist()
  27. {
  28. var insight = await _sut.GetHouseholdPriceInsightAsync(Guid.NewGuid(), Guid.NewGuid());
  29. Assert.Null(insight);
  30. }
  31. [Fact]
  32. public async Task RecordObservationAsync_ThenGetInsight_ReturnsLatestAverageMedianAndLowest()
  33. {
  34. var householdId = Guid.NewGuid();
  35. var productId = Guid.NewGuid();
  36. await _sut.RecordObservationAsync(productId, 3.00m, Now.AddDays(-2), PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
  37. await _sut.RecordObservationAsync(productId, 5.00m, Now.AddDays(-1), PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
  38. await _sut.RecordObservationAsync(productId, 4.00m, Now, PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
  39. var insight = await _sut.GetHouseholdPriceInsightAsync(householdId, productId);
  40. Assert.NotNull(insight);
  41. Assert.Equal(3, insight!.ObservationCount);
  42. Assert.Equal(4.00m, insight.LatestPrice);
  43. Assert.Equal(Now, insight.LatestObservedUtc);
  44. Assert.Equal(4.00m, insight.AveragePrice);
  45. Assert.Equal(4.00m, insight.MedianPrice);
  46. Assert.Equal(3.00m, insight.LowestPrice);
  47. }
  48. [Fact]
  49. public async Task GetHouseholdPriceInsightAsync_ComputesMedianForEvenCount()
  50. {
  51. var householdId = Guid.NewGuid();
  52. var productId = Guid.NewGuid();
  53. await _sut.RecordObservationAsync(productId, 2.00m, Now.AddDays(-1), PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
  54. await _sut.RecordObservationAsync(productId, 4.00m, Now, PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
  55. var insight = await _sut.GetHouseholdPriceInsightAsync(householdId, productId);
  56. Assert.Equal(3.00m, insight!.MedianPrice);
  57. }
  58. [Fact]
  59. public async Task GetHouseholdPriceInsightAsync_DoesNotMixDifferentHouseholds()
  60. {
  61. var productId = Guid.NewGuid();
  62. await _sut.RecordObservationAsync(productId, 3.00m, Now, PriceObservationSourceType.UserEntered, 1m, householdId: Guid.NewGuid());
  63. var insight = await _sut.GetHouseholdPriceInsightAsync(Guid.NewGuid(), productId);
  64. Assert.Null(insight);
  65. }
  66. [Fact]
  67. public async Task GetHouseholdPriceHistoryAsync_ReturnsNewestFirst()
  68. {
  69. var householdId = Guid.NewGuid();
  70. var productId = Guid.NewGuid();
  71. await _sut.RecordObservationAsync(productId, 3.00m, Now.AddDays(-1), PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
  72. await _sut.RecordObservationAsync(productId, 4.00m, Now, PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
  73. var history = await _sut.GetHouseholdPriceHistoryAsync(householdId, productId);
  74. Assert.Equal(2, history.Count);
  75. Assert.Equal(4.00m, history[0].Price);
  76. Assert.Equal(3.00m, history[1].Price);
  77. }
  78. [Fact]
  79. public async Task GetHouseholdPricedProductsAsync_ReturnsEmptyWhenNoObservationsExist()
  80. {
  81. var products = await _sut.GetHouseholdPricedProductsAsync(Guid.NewGuid());
  82. Assert.Empty(products);
  83. }
  84. [Fact]
  85. public async Task GetHouseholdPricedProductsAsync_GroupsByProductAndSortsByName()
  86. {
  87. var householdId = Guid.NewGuid();
  88. var milk = new Product("Milk", ProductSourceType.Manual, Now);
  89. var bread = new Product("Bread", ProductSourceType.Manual, Now);
  90. _db.Products.Add(milk);
  91. _db.Products.Add(bread);
  92. await _db.SaveChangesAsync();
  93. await _sut.RecordObservationAsync(milk.ProductId, 3.00m, Now.AddDays(-1), PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
  94. await _sut.RecordObservationAsync(milk.ProductId, 4.00m, Now, PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
  95. await _sut.RecordObservationAsync(bread.ProductId, 2.50m, Now, PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
  96. var products = await _sut.GetHouseholdPricedProductsAsync(householdId);
  97. Assert.Equal(2, products.Count);
  98. Assert.Equal("Bread", products[0].ProductName);
  99. Assert.Equal("Milk", products[1].ProductName);
  100. Assert.Equal(2, products[1].ObservationCount);
  101. Assert.Equal(4.00m, products[1].LatestPrice);
  102. Assert.Equal(3.50m, products[1].AveragePrice);
  103. Assert.Equal(3.00m, products[1].LowestPrice);
  104. }
  105. [Fact]
  106. public async Task GetHouseholdPricedProductsAsync_DoesNotMixDifferentHouseholds()
  107. {
  108. var milk = new Product("Milk", ProductSourceType.Manual, Now);
  109. _db.Products.Add(milk);
  110. await _db.SaveChangesAsync();
  111. await _sut.RecordObservationAsync(milk.ProductId, 3.00m, Now, PriceObservationSourceType.UserEntered, 1m, householdId: Guid.NewGuid());
  112. var products = await _sut.GetHouseholdPricedProductsAsync(Guid.NewGuid());
  113. Assert.Empty(products);
  114. }
  115. }

Powered by TurnKey Linux.