You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

765 lines
28 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
using Moq;
using Microsoft.AspNetCore.Mvc;
using Haoliang.Api.Controllers;
using Haoliang.Core.Services;
using Haoliang.Models.Models.System;
using Haoliang.Models.Models.Production;
using Haoliang.Models.Common;
namespace Haoliang.Tests.Controllers
{
public class StatisticsControllerTests
{
private readonly Mock<IProductionStatisticsService> _mockStatisticsService;
private readonly StatisticsController _controller;
public StatisticsControllerTests()
{
_mockStatisticsService = new Mock<IProductionStatisticsService>();
_controller = new StatisticsController(_mockStatisticsService.Object);
}
[Fact]
public async Task GetProductionTrendsAsync_ValidRequest_ReturnsOk()
{
// Arrange
var deviceId = 1;
var startDate = DateTime.Now.AddDays(-7);
var endDate = DateTime.Now;
var trendAnalysis = new ProductionTrendAnalysis
{
DeviceId = deviceId,
DeviceName = "Test Device",
PeriodStart = startDate,
PeriodEnd = endDate,
TotalProduction = 1000,
AverageDailyProduction = 142.86m,
TrendCoefficient = 0.5m,
TrendDirection = ProductionTrendDirection.Increasing,
DailyData = new List<DailyProduction>()
};
_mockStatisticsService.Setup(service => service.CalculateProductionTrendsAsync(deviceId, startDate, endDate))
.ReturnsAsync(trendAnalysis);
// Act
var result = await _controller.GetProductionTrends(deviceId, startDate, endDate);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<ProductionTrendAnalysis>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(trendAnalysis, response.Data);
}
[Fact]
public async Task GetProductionTrendsAsync_InvalidDevice_ReturnsNotFound()
{
// Arrange
var deviceId = 999;
var startDate = DateTime.Now.AddDays(-7);
var endDate = DateTime.Now;
_mockStatisticsService.Setup(service => service.CalculateProductionTrendsAsync(deviceId, startDate, endDate))
.ThrowsAsync(new KeyNotFoundException("Device not found"));
// Act
var result = await _controller.GetProductionTrends(deviceId, startDate, endDate);
// Assert
var notFoundResult = Assert.IsType<NotFoundObjectResult>(result);
var response = Assert.IsType<ApiResponse<ProductionTrendAnalysis>>(notFoundResult.Value);
Assert.False(response.Success);
Assert.Contains("Device not found", response.Message);
}
[Fact]
public async Task GetProductionReportAsync_ValidFilter_ReturnsOk()
{
// Arrange
var filter = new ReportFilter
{
DeviceIds = new List<int> { 1 },
StartDate = DateTime.Now.AddDays(-7),
EndDate = DateTime.Now,
ReportType = ReportType.Daily
};
var productionReport = new ProductionReport
{
ReportDate = DateTime.Now,
ReportType = ReportType.Daily,
SummaryItems = new List<ProductionSummaryItem>(),
Metadata = ReportMetadata.GeneratedAt
};
_mockStatisticsService.Setup(service => service.GenerateProductionReportAsync(filter))
.ReturnsAsync(productionReport);
// Act
var result = await _controller.GetProductionReport(filter);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<ProductionReport>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(productionReport, response.Data);
}
[Fact]
public async Task GetDashboardSummaryAsync_ValidFilter_ReturnsOk()
{
// Arrange
var filter = new DashboardFilter
{
DeviceIds = new List<int> { 1 },
Date = DateTime.Today,
IncludeAlerts = true
};
var dashboardSummary = new DashboardSummary
{
GeneratedAt = DateTime.Now,
TotalDevices = 10,
ActiveDevices = 8,
OfflineDevices = 2,
TotalProductionToday = 1000,
TotalProductionThisWeek = 7000,
TotalProductionThisMonth = 30000,
OverallEfficiency = 85.5m,
QualityRate = 98.2m,
DeviceSummaries = new List<DeviceSummary>(),
ActiveAlerts = new List<AlertSummary>()
};
_mockStatisticsService.Setup(service => service.GetDashboardSummaryAsync(filter))
.ReturnsAsync(dashboardSummary);
// Act
var result = await _controller.GetDashboardSummary(filter);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<DashboardSummary>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(dashboardSummary, response.Data);
}
[Fact]
public async Task GetEfficiencyMetricsAsync_ValidFilter_ReturnsOk()
{
// Arrange
var filter = new EfficiencyFilter
{
DeviceIds = new List<int> { 1 },
StartDate = DateTime.Now.AddDays(-7),
EndDate = DateTime.Now,
Metrics = EfficiencyMetric.Oee
};
var efficiencyMetrics = new EfficiencyMetrics
{
DeviceId = 1,
DeviceName = "Test Device",
PeriodStart = DateTime.Now.AddDays(-7),
PeriodEnd = DateTime.Now,
Availability = 95m,
Performance = 90m,
Quality = 98m,
Oee = 83.79m,
Utilization = EquipmentUtilization.Optimal,
HourlyData = new List<HourlyEfficiency>()
};
_mockStatisticsService.Setup(service => service.CalculateEfficiencyMetricsAsync(filter))
.ReturnsAsync(efficiencyMetrics);
// Act
var result = await _controller.GetEfficiencyMetrics(filter);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<EfficiencyMetrics>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(efficiencyMetrics, response.Data);
}
[Fact]
public async Task GetOeeMetricsAsync_ValidDeviceAndDate_ReturnsOk()
{
// Arrange
var deviceId = 1;
var date = DateTime.Today;
var oeeMetrics = new OeeMetrics
{
DeviceId = deviceId,
DeviceName = "Test Device",
Date = date,
Availability = 95m,
Performance = 90m,
Quality = 98m,
Oee = 83.79m,
PlannedProductionTime = TimeSpan.FromHours(8),
ActualProductionTime = TimeSpan.FromHours(7.6),
Downtime = TimeSpan.FromMinutes(24),
IdealCycleTime = 2,
TotalCycleTime = 500,
TotalPieces = 250,
GoodPieces = 245
};
_mockStatisticsService.Setup(service => service.CalculateOeeAsync(deviceId, date))
.ReturnsAsync(oeeMetrics);
// Act
var result = await _controller.GetOeeMetrics(deviceId, date);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<OeeMetrics>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(oeeMetrics, response.Data);
}
[Fact]
public async Task GetProductionForecastAsync_ValidFilter_ReturnsOk()
{
// Arrange
var filter = new ForecastFilter
{
DeviceId = 1,
DaysToForecast = 7,
Model = ForecastModel.Linear,
HistoricalDataStart = DateTime.Now.AddDays(-30),
HistoricalDataEnd = DateTime.Now
};
var productionForecast = new ProductionForecast
{
DeviceId = 1,
DeviceName = "Test Device",
ForecastStartDate = DateTime.Today,
ForecastEndDate = DateTime.Today.AddDays(6),
DailyForecasts = new List<ForecastItem>(),
ForecastAccuracy = 85.5m,
ModelUsed = ForecastModel.Linear
};
_mockStatisticsService.Setup(service => service.GenerateProductionForecastAsync(filter))
.ReturnsAsync(productionForecast);
// Act
var result = await _controller.GetProductionForecast(filter);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<ProductionForecast>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(productionForecast, response.Data);
}
[Fact]
public async Task DetectProductionAnomaliesAsync_ValidFilter_ReturnsOk()
{
// Arrange
var filter = new AnomalyFilter
{
DeviceIds = new List<int> { 1 },
StartDate = DateTime.Now.AddDays(-7),
EndDate = DateTime.Now,
MinSeverity = AnomalySeverity.Medium
};
var anomalyAnalysis = new AnomalyAnalysis
{
DeviceIds = new List<int> { 1 },
DeviceNames = new List<string> { "Test Device" },
AnalysisStartDate = DateTime.Now.AddDays(-7),
AnalysisEndDate = DateTime.Now,
Anomalies = new List<ProductionAnomaly>(),
OverallSeverity = AnomalySeverity.Low
};
_mockStatisticsService.Setup(service => service.DetectProductionAnomaliesAsync(filter))
.ReturnsAsync(anomalyAnalysis);
// Act
var result = await _controller.DetectProductionAnomalies(filter);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<AnomalyAnalysis>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(anomalyAnalysis, response.Data);
}
[Fact]
public async Task GetHistoricalProductionDataAsync_ValidRequest_ReturnsOk()
{
// Arrange
var deviceId = 1;
var startDate = DateTime.Now.AddDays(-7);
var endDate = DateTime.Now;
var groupBy = GroupBy.Date;
var historicalData = new HistoricalProductionData
{
DeviceId = deviceId,
PeriodStart = startDate,
PeriodEnd = endDate,
GroupBy = groupBy,
DataPoints = new List<DataPoint>()
};
_mockStatisticsService.Setup(service => service.GenerateProductionReportAsync(It.IsAny<ReportFilter>()))
.ReturnsAsync(new ProductionReport { SummaryItems = new List<ProductionSummaryItem>() });
// Mock the conversion in the controller
// This would normally be done by the controller logic
// Act
var result = await _controller.GetHistoricalProductionData(deviceId, startDate, endDate, groupBy);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<HistoricalProductionData>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(deviceId, response.Data.DeviceId);
}
[Fact]
public async Task GetHistoricalProductionDataAsync_InvalidDevice_ReturnsBadRequest()
{
// Arrange
var deviceId = 0; // Invalid device ID
var startDate = DateTime.Now.AddDays(-7);
var endDate = DateTime.Now;
// Act
var result = await _controller.GetHistoricalProductionData(deviceId, startDate, endDate);
// Assert
var badRequestResult = Assert.IsType<BadRequestObjectResult>(result);
var response = Assert.IsType<ApiResponse<HistoricalProductionData>>(badRequestResult.Value);
Assert.False(response.Success);
Assert.Contains("Invalid device ID", response.Message);
}
[Fact]
public async Task GetEfficiencyTrendsAsync_ValidRequest_ReturnsOk()
{
// Arrange
var deviceId = 1;
var startDate = DateTime.Now.AddDays(-7);
var endDate = DateTime.Now;
var metric = EfficiencyMetric.Oee;
var efficiencyTrendData = new EfficiencyTrendData
{
DeviceId = deviceId,
Metric = metric,
PeriodStart = startDate,
PeriodEnd = endDate,
DataPoints = new List<EfficiencyDataPoint>()
};
_mockStatisticsService.Setup(service => service.CalculateEfficiencyMetricsAsync(It.IsAny<EfficiencyFilter>()))
.ReturnsAsync(new EfficiencyMetrics { HourlyData = new List<HourlyEfficiency>() });
// Act
var result = await _controller.GetEfficiencyTrends(deviceId, startDate, endDate, metric);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<EfficiencyTrendData>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(deviceId, response.Data.DeviceId);
}
[Fact]
public async Task GetMultiDeviceSummaryAsync_ValidDevices_ReturnsOk()
{
// Arrange
var deviceIds = new List<int> { 1, 2, 3 };
_mockStatisticsService.Setup(service => service.GetDashboardSummaryAsync(It.IsAny<DashboardFilter>()))
.ReturnsAsync(new DashboardSummary
{
TotalDevices = 3,
ActiveDevices = 2,
OfflineDevices = 1,
TotalProductionToday = 1000,
TotalProductionThisWeek = 7000,
TotalProductionThisMonth = 30000,
OverallEfficiency = 85.5m,
QualityRate = 98.2m,
DeviceSummaries = new List<DeviceSummary>()
});
// Act
var result = await _controller.GetMultiDeviceSummary(deviceIds);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<MultiDeviceSummary>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(3, response.Data.DeviceCount);
Assert.Equal(2, response.Data.ActiveDeviceCount);
Assert.Equal(1, response.Data.OfflineDeviceCount);
}
}
public class ConfigControllerTests
{
private readonly Mock<ISystemService> _mockSystemService;
private readonly Mock<ITemplateService> _mockTemplateService;
private readonly Mock<IRulesService> _mockRulesService;
private readonly Mock<IProductionStatisticsService> _mockStatisticsService;
private readonly ConfigController _controller;
public ConfigControllerTests()
{
_mockSystemService = new Mock<ISystemService>();
_mockTemplateService = new Mock<ITemplateService>();
_mockRulesService = new Mock<IRulesService>();
_mockStatisticsService = new Mock<IProductionStatisticsService>();
_controller = new ConfigController(
_mockSystemService.Object,
_mockTemplateService.Object,
_mockRulesService.Object,
_mockStatisticsService.Object
);
}
[Fact]
public async Task GetSystemConfigurationAsync_ValidRequest_ReturnsOk()
{
// Arrange
var systemConfig = new SystemConfiguration
{
DailyProductionTarget = 100,
EnableProduction = true,
EnableAlerts = true,
AlertThresholds = new Dictionary<string, decimal>
{
{ "production_drop", 30 },
{ "quality_rate", 90 }
}
};
_mockSystemService.Setup(service => service.GetSystemConfigurationAsync())
.ReturnsAsync(systemConfig);
// Act
var result = await _controller.GetSystemConfiguration();
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<SystemConfiguration>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(systemConfig, response.Data);
}
[Fact]
public async Task UpdateSystemConfigurationAsync_ValidConfig_ReturnsOk()
{
// Arrange
var config = new SystemConfiguration
{
DailyProductionTarget = 150,
EnableProduction = true,
EnableAlerts = true
};
_mockSystemService.Setup(service => service.UpdateSystemConfigurationAsync(config))
.ReturnsAsync(true);
// Act
var result = await _controller.UpdateSystemConfiguration(config);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<bool>>(okResult.Value);
Assert.True(response.Success);
Assert.True(response.Data);
}
[Fact]
public async Task GetProductionTargetsAsync_ValidRequest_ReturnsOk()
{
// Arrange
var targets = new List<ProductionTargetConfig>
{
new ProductionTargetConfig { DeviceId = 1, ProgramName = "Program1", DailyTarget = 100 },
new ProductionTargetConfig { DeviceId = 2, ProgramName = "Program2", DailyTarget = 150 }
};
_mockSystemService.Setup(service => service.GetProductionTargetsAsync())
.ReturnsAsync(targets);
// Act
var result = await _controller.GetProductionTargets();
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<List<ProductionTargetConfig>>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(2, response.Data.Count);
}
[Fact]
public async Task GetWorkingHoursConfigAsync_ValidRequest_ReturnsOk()
{
// Arrange
var workingHoursConfig = new WorkingHoursConfig
{
WorkingDays = new List<DayOfWeek> { DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday },
WorkingHours = TimeSpan.FromHours(8),
StartHour = 9,
EndHour = 17,
BreakIntervals = new List<TimeSpan>
{
TimeSpan.FromHours(12) // Lunch break
}
};
_mockSystemService.Setup(service => service.GetWorkingHoursConfigAsync())
.ReturnsAsync(workingHoursConfig);
// Act
var result = await _controller.GetWorkingHoursConfig();
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<WorkingHoursConfig>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(5, response.Data.WorkingDays.Count);
}
[Fact]
public async Task GetAlertConfigurationAsync_ValidRequest_ReturnsOk()
{
// Arrange
var alertConfig = new AlertConfiguration
{
EnableAlerts = true,
AlertTypes = new List<string> { "production_drop", "quality_rate", "device_error" },
AlertThresholds = new Dictionary<string, decimal>
{
{ "production_drop", 30 },
{ "quality_rate", 90 },
{ "device_error", 5 }
},
NotificationChannels = new List<string> { "email", "sms", "webhook" }
};
_mockSystemService.Setup(service => service.GetAlertConfigurationAsync())
.ReturnsAsync(alertConfig);
// Act
var result = await _controller.GetAlertConfiguration();
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<AlertConfiguration>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(3, response.Data.AlertTypes.Count);
}
[Fact]
public async Task GetBusinessRulesAsync_ValidRequest_ReturnsOk()
{
// Arrange
var rules = new List<BusinessRuleConfig>
{
new BusinessRuleConfig { RuleId = 1, RuleName = "Production Target", Enabled = true },
new BusinessRuleConfig { RuleId = 2, RuleName = "Quality Control", Enabled = false }
};
_mockRulesService.Setup(service => service.GetAllRulesAsync())
.ReturnsAsync(rules);
// Act
var result = await _controller.GetBusinessRules();
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<List<BusinessRuleConfig>>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(2, response.Data.Count);
}
[Fact]
public async Task CreateOrUpdateBusinessRuleAsync_ValidRule_ReturnsOk()
{
// Arrange
var rule = new BusinessRuleConfig
{
RuleId = 1,
RuleName = "Production Target",
Enabled = true,
RuleExpression = "production > target * 0.9"
};
_mockRulesService.Setup(service => service.CreateOrUpdateRuleAsync(rule))
.ReturnsAsync(rule);
// Act
var result = await _controller.CreateOrUpdateBusinessRule(rule);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<BusinessRuleConfig>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(rule, response.Data);
}
[Fact]
public async Task DeleteBusinessRuleAsync_ValidRuleId_ReturnsOk()
{
// Arrange
var ruleId = 1;
_mockRulesService.Setup(service => service.DeleteRuleAsync(ruleId))
.ReturnsAsync(true);
// Act
var result = await _controller.DeleteBusinessRule(ruleId);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<bool>>(okResult.Value);
Assert.True(response.Success);
Assert.True(response.Data);
}
[Fact]
public async Task GetStatisticsRulesAsync_ValidRequest_ReturnsOk()
{
// Arrange
var rules = new List<StatisticsRuleConfig>
{
new StatisticsRuleConfig { RuleId = 1, RuleName = "Production Trend", Enabled = true },
new StatisticsRuleConfig { RuleId = 2, RuleName = "Efficiency Analysis", Enabled = true }
};
_mockRulesService.Setup(service => service.GetStatisticsRulesAsync())
.ReturnsAsync(rules);
// Act
var result = await _controller.GetStatisticsRules();
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<List<StatisticsRuleConfig>>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(2, response.Data.Count);
}
[Fact]
public async Task GetDataRetentionConfigAsync_ValidRequest_ReturnsOk()
{
// Arrange
var retentionConfig = new DataRetentionConfig
{
BusinessDataRetentionDays = 365,
LogDataRetentionDays = 90,
StatisticsDataRetentionDays = 180,
AutoCleanupEnabled = true,
CleanupSchedule = "0 2 * * *" // Daily at 2 AM
};
_mockSystemService.Setup(service => service.GetDataRetentionConfigAsync())
.ReturnsAsync(retentionConfig);
// Act
var result = await _controller.GetDataRetentionConfig();
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<DataRetentionConfig>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(365, response.Data.BusinessDataRetentionDays);
}
[Fact]
public async Task GetDashboardConfigAsync_ValidRequest_ReturnsOk()
{
// Arrange
var dashboardConfig = new DashboardConfig
{
RefreshInterval = 30,
EnableRealTimeUpdates = true,
DefaultTimeRange = "7d",
AvailableTimeRanges = new List<string> { "1d", "7d", "30d", "90d" },
AvailableWidgets = new List<string> { "production_chart", "efficiency_chart", "device_status" }
};
_mockSystemService.Setup(service => service.GetDashboardConfigAsync())
.ReturnsAsync(dashboardConfig);
// Act
var result = await _controller.GetDashboardConfig();
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<DashboardConfig>>(okResult.Value);
Assert.True(response.Success);
Assert.Equal(30, response.Data.RefreshInterval);
}
[Fact]
public async Task ValidateConfigurationAsync_ValidConfig_ReturnsOk()
{
// Arrange
var config = new SystemConfiguration { DailyProductionTarget = 100 };
var validationResult = new ValidationResult
{
IsValid = true,
Errors = new List<string>(),
Warnings = new List<string>()
};
_mockSystemService.Setup(service => service.ValidateConfigurationAsync(config))
.ReturnsAsync(validationResult);
// Act
var result = await _controller.ValidateConfiguration(config);
// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var response = Assert.IsType<ApiResponse<ValidationResult>>(okResult.Value);
Assert.True(response.Success);
Assert.True(response.Data.IsValid);
}
[Fact]
public async Task ExportConfigurationAsync_ValidRequest_ReturnsFile()
{
// Arrange
var config = new SystemConfiguration
{
DailyProductionTarget = 100,
EnableProduction = true,
EnableAlerts = true
};
_mockSystemService.Setup(service => service.GetSystemConfigurationAsync())
.ReturnsAsync(config);
// Act
var result = await _controller.ExportConfiguration();
// Assert
var fileResult = Assert.IsType<FileContentResult>(result);
Assert.Contains("system-configuration.json", fileResult.FileDownloadName);
}
}
}