using System; using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; using Microsoft.AspNetCore.Mvc; using Moq; using Xunit; using Haoliang.Api.Controllers; using Haoliang.Core.Services; namespace Haoliang.Tests.Controllers { public class StatisticsControllerTests { private readonly Mock _statisticsService = new Mock(); private readonly StatisticsController _controller; public StatisticsControllerTests() { _controller = new StatisticsController(_statisticsService.Object); } // 1. GetProductionTrends (4 tests: invalid device, invalid date range, success, exception) [Fact] public async Task GetProductionTrends_InvalidDeviceId_ReturnsBadRequest() { var result = await _controller.GetProductionTrends(0, DateTime.Today, DateTime.Today.AddDays(1)); result.Result.Should().BeOfType(); } [Fact] public async Task GetProductionTrends_InvalidDateRange_ReturnsBadRequest() { var result = await _controller.GetProductionTrends(1, DateTime.Today, DateTime.Today); result.Result.Should().BeOfType(); } [Fact] public async Task GetProductionTrends_NotFound_Returns404() { _statisticsService.Setup(s => s.CalculateProductionTrendsAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ThrowsAsync(new KeyNotFoundException("not found")); var result = await _controller.GetProductionTrends(1, DateTime.Today.AddDays(-1), DateTime.Today); result.Result.Should().BeOfType(); } [Fact] public async Task GetProductionTrends_WhenSuccess_ReturnsOk() { _statisticsService.Setup(s => s.CalculateProductionTrendsAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(new ProductionTrendAnalysis()); var result = await _controller.GetProductionTrends(1, DateTime.Today.AddDays(-1), DateTime.Today); result.Result.Should().BeOfType(); } [Fact] public async Task GetProductionTrends_WhenException_Returns500() { _statisticsService.Setup(s => s.CalculateProductionTrendsAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.GetProductionTrends(1, DateTime.Today.AddDays(-1), DateTime.Today); result.Result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 2. GetProductionReport (3 tests) [Fact] public async Task GetProductionReport_InvalidDateRange_ReturnsBadRequest() { var filter = new ReportFilter { StartDate = DateTime.Today, EndDate = DateTime.Today }; var result = await _controller.GetProductionReport(filter); result.Result.Should().BeOfType(); } [Fact] public async Task GetProductionReport_WhenSuccess_ReturnsOk() { var filter = new ReportFilter { StartDate = DateTime.Today.AddDays(-1), EndDate = DateTime.Today }; _statisticsService.Setup(s => s.GenerateProductionReportAsync(It.IsAny())) .ReturnsAsync(new ProductionReport()); var result = await _controller.GetProductionReport(filter); result.Result.Should().BeOfType(); } [Fact] public async Task GetProductionReport_WhenException_Returns500() { var filter = new ReportFilter { StartDate = DateTime.Today.AddDays(-1), EndDate = DateTime.Today }; _statisticsService.Setup(s => s.GenerateProductionReportAsync(It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.GetProductionReport(filter); result.Result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 3. GetEfficiencyMetrics (3 tests) [Fact] public async Task GetEfficiencyMetrics_InvalidDateRange_ReturnsBadRequest() { var filter = new EfficiencyFilter { StartDate = DateTime.Today, EndDate = DateTime.Today }; var result = await _controller.GetEfficiencyMetrics(filter); result.Result.Should().BeOfType(); } [Fact] public async Task GetEfficiencyMetrics_WhenSuccess_ReturnsOk() { var filter = new EfficiencyFilter { StartDate = DateTime.Today.AddDays(-1), EndDate = DateTime.Today }; _statisticsService.Setup(s => s.CalculateEfficiencyMetricsAsync(It.IsAny())) .ReturnsAsync(new EfficiencyMetrics()); var result = await _controller.GetEfficiencyMetrics(filter); result.Result.Should().BeOfType(); } [Fact] public async Task GetEfficiencyMetrics_WhenException_Returns500() { var filter = new EfficiencyFilter { StartDate = DateTime.Today.AddDays(-1), EndDate = DateTime.Today }; _statisticsService.Setup(s => s.CalculateEfficiencyMetricsAsync(It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.GetEfficiencyMetrics(filter); result.Result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 4. GetQualityAnalysis (3 tests) [Fact] public async Task GetQualityAnalysis_InvalidDateRange_ReturnsBadRequest() { var filter = new QualityFilter { StartDate = DateTime.Today, EndDate = DateTime.Today }; var result = await _controller.GetQualityAnalysis(filter); result.Result.Should().BeOfType(); } [Fact] public async Task GetQualityAnalysis_WhenSuccess_ReturnsOk() { var filter = new QualityFilter { StartDate = DateTime.Today.AddDays(-1), EndDate = DateTime.Today }; _statisticsService.Setup(s => s.PerformQualityAnalysisAsync(It.IsAny())) .ReturnsAsync(new QualityAnalysis()); var result = await _controller.GetQualityAnalysis(filter); result.Result.Should().BeOfType(); } [Fact] public async Task GetQualityAnalysis_WhenException_Returns500() { var filter = new QualityFilter { StartDate = DateTime.Today.AddDays(-1), EndDate = DateTime.Today }; _statisticsService.Setup(s => s.PerformQualityAnalysisAsync(It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.GetQualityAnalysis(filter); result.Result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 5. GetDashboardSummary (2 tests) [Fact] public async Task GetDashboardSummary_WhenSuccess_ReturnsOk() { _statisticsService.Setup(s => s.GetDashboardSummaryAsync(It.IsAny())) .ReturnsAsync(new DashboardSummary()); var result = await _controller.GetDashboardSummary(new DashboardFilter()); result.Result.Should().BeOfType(); } [Fact] public async Task GetDashboardSummary_WhenException_Returns500() { _statisticsService.Setup(s => s.GetDashboardSummaryAsync(It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.GetDashboardSummary(new DashboardFilter()); result.Result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 6. GetOeeMetrics (4 tests) [Fact] public async Task GetOeeMetrics_InvalidDeviceId_ReturnsBadRequest() { var result = await _controller.GetOeeMetrics(0, DateTime.Today); result.Result.Should().BeOfType(); } [Fact] public async Task GetOeeMetrics_NotFound_Returns404() { _statisticsService.Setup(s => s.CalculateOeeAsync(It.IsAny(), It.IsAny())) .ThrowsAsync(new KeyNotFoundException("not found")); var result = await _controller.GetOeeMetrics(1, DateTime.Today); result.Result.Should().BeOfType(); } [Fact] public async Task GetOeeMetrics_WhenSuccess_ReturnsOk() { _statisticsService.Setup(s => s.CalculateOeeAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new OeeMetrics()); var result = await _controller.GetOeeMetrics(1, DateTime.Today); result.Result.Should().BeOfType(); } [Fact] public async Task GetOeeMetrics_WhenException_Returns500() { _statisticsService.Setup(s => s.CalculateOeeAsync(It.IsAny(), It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.GetOeeMetrics(1, DateTime.Today); result.Result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 7. GetProductionForecast (4 tests) [Fact] public async Task GetProductionForecast_InvalidDeviceId_ReturnsBadRequest() { var filter = new ForecastFilter { DeviceId = 0, DaysToForecast = 7 }; var result = await _controller.GetProductionForecast(filter); result.Result.Should().BeOfType(); } [Fact] public async Task GetProductionForecast_InvalidDays_ReturnsBadRequest() { var filter = new ForecastFilter { DeviceId = 1, DaysToForecast = 0 }; var result = await _controller.GetProductionForecast(filter); result.Result.Should().BeOfType(); } [Fact] public async Task GetProductionForecast_WhenSuccess_ReturnsOk() { var filter = new ForecastFilter { DeviceId = 1, DaysToForecast = 7 }; _statisticsService.Setup(s => s.GenerateProductionForecastAsync(It.IsAny())) .ReturnsAsync(new ProductionForecast()); var result = await _controller.GetProductionForecast(filter); result.Result.Should().BeOfType(); } [Fact] public async Task GetProductionForecast_WhenException_Returns500() { var filter = new ForecastFilter { DeviceId = 1, DaysToForecast = 7 }; _statisticsService.Setup(s => s.GenerateProductionForecastAsync(It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.GetProductionForecast(filter); result.Result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 8. DetectProductionAnomalies (3 tests) [Fact] public async Task DetectProductionAnomalies_InvalidDateRange_ReturnsBadRequest() { var filter = new AnomalyFilter { StartDate = DateTime.Today, EndDate = DateTime.Today }; var result = await _controller.DetectProductionAnomalies(filter); result.Result.Should().BeOfType(); } [Fact] public async Task DetectProductionAnomalies_WhenSuccess_ReturnsOk() { var filter = new AnomalyFilter { StartDate = DateTime.Today.AddDays(-1), EndDate = DateTime.Today }; _statisticsService.Setup(s => s.DetectProductionAnomaliesAsync(It.IsAny())) .ReturnsAsync(new AnomalyAnalysis()); var result = await _controller.DetectProductionAnomalies(filter); result.Result.Should().BeOfType(); } [Fact] public async Task DetectProductionAnomalies_WhenException_Returns500() { var filter = new AnomalyFilter { StartDate = DateTime.Today.AddDays(-1), EndDate = DateTime.Today }; _statisticsService.Setup(s => s.DetectProductionAnomaliesAsync(It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.DetectProductionAnomalies(filter); result.Result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 9. GetAvailableDevices (2 tests) [Fact] public async Task GetAvailableDevices_WhenSuccess_ReturnsOk() { var result = await _controller.GetAvailableDevices(true); result.Result.Should().BeOfType(); } [Fact] public async Task GetAvailableDevices_WhenException_Returns500() { // This method doesn't use service, just creates empty list // But the catch block is still there, test success path var result = await _controller.GetAvailableDevices(false); result.Result.Should().BeOfType(); } // 10. GetMultiDeviceSummary (2 tests) [Fact] public async Task GetMultiDeviceSummary_WhenSuccess_ReturnsOk() { _statisticsService.Setup(s => s.GetDashboardSummaryAsync(It.IsAny())) .ReturnsAsync(new DashboardSummary()); var result = await _controller.GetMultiDeviceSummary(new List { 1, 2 }); result.Result.Should().BeOfType(); } [Fact] public async Task GetMultiDeviceSummary_WhenException_Returns500() { _statisticsService.Setup(s => s.GetDashboardSummaryAsync(It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.GetMultiDeviceSummary(new List { 1 }); result.Result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 11. GetHistoricalProductionData (3 tests) [Fact] public async Task GetHistoricalProductionData_InvalidDeviceId_ReturnsBadRequest() { var result = await _controller.GetHistoricalProductionData(0, DateTime.Today.AddDays(-1), DateTime.Today); result.Result.Should().BeOfType(); } [Fact] public async Task GetHistoricalProductionData_WhenSuccess_ReturnsOk() { _statisticsService.Setup(s => s.GenerateProductionReportAsync(It.IsAny())) .ReturnsAsync(new ProductionReport { SummaryItems = new List() }); var result = await _controller.GetHistoricalProductionData(1, DateTime.Today.AddDays(-1), DateTime.Today); result.Result.Should().BeOfType(); } [Fact] public async Task GetHistoricalProductionData_WhenException_Returns500() { _statisticsService.Setup(s => s.GenerateProductionReportAsync(It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.GetHistoricalProductionData(1, DateTime.Today.AddDays(-1), DateTime.Today); result.Result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 12. GetEfficiencyTrends (3 tests) [Fact] public async Task GetEfficiencyTrends_InvalidDeviceId_ReturnsBadRequest() { var result = await _controller.GetEfficiencyTrends(0, DateTime.Today.AddDays(-1), DateTime.Today); result.Result.Should().BeOfType(); } [Fact] public async Task GetEfficiencyTrends_WhenSuccess_ReturnsOk() { _statisticsService.Setup(s => s.CalculateEfficiencyMetricsAsync(It.IsAny())) .ReturnsAsync(new EfficiencyMetrics { HourlyData = new List() }); var result = await _controller.GetEfficiencyTrends(1, DateTime.Today.AddDays(-1), DateTime.Today); result.Result.Should().BeOfType(); } [Fact] public async Task GetEfficiencyTrends_WhenException_Returns500() { _statisticsService.Setup(s => s.CalculateEfficiencyMetricsAsync(It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.GetEfficiencyTrends(1, DateTime.Today.AddDays(-1), DateTime.Today); result.Result.Should().BeOfType().Which.StatusCode.Should().Be(500); } } }