using System;
using System.Threading;
using Xunit;
using CncCollector.Core;
using CncCollector.Config;
using CncModels.Entity;
using Moq; // 测试项目常用依赖,当前测试未直接使用 Mock,但保留以匹配项目风格
namespace CncCollector.Tests
{
///
/// CollectWorker 的单元测试集合(针对构造与基本控制流程)。
/// 使用无效的数据库连接和无效的 HTTP 地址,确保线程启动/停止的行为在异常情况下也能健壮执行。
///
public class CollectWorkerTests : IDisposable
{
private CollectWorker _worker;
private CollectAddress _address;
private CollectorConfig _config;
///
/// 创建一个 CollectWorker 实例,方便各测试用例复用。
/// 注:为了测试稳定性,数据库连接字符串与 URL 使用无效值。
///
private void CreateWorker()
{
_address = new CollectAddress
{
Id = 1,
Name = "TestAddress",
Url = "http://invalid.localhost/health", // 无效地址,避免真实网络请求
BrandId = 1,
CollectInterval = 1 // 1 秒间隔,便于测试快速循环
};
_config = new CollectorConfig();
// 无效连接字符串,确保不会真正连接到数据库
string businessConn = "Server=.;Database=NonExistingDb;User Id=invalid;Password=invalid;";
string logConn = "Server=.;Database=NonExistingLogDb;User Id=invalid;Password=invalid;";
// 允许 tracker 为 null,因为在无效 URL 的测试路径下通常不会进入需要 Tracker 的分支
_worker = new CollectWorker(_address, _config, null, businessConn, logConn);
}
public void Dispose()
{
if (_worker != null)
{
try { _worker.Stop(); } catch { /* 忽略停止时的异常,确保测试清理安全 */ }
}
}
///
/// 构造函数_正常创建_属性正确
/// 验证 AddressId, AddressName, IsRunning, LastCollectTime, SuccessCount, FailCount
///
[Fact]
public void 构造函数_正常创建_属性正确()
{
CreateWorker();
Assert.Equal(1, _worker.AddressId);
Assert.Equal("TestAddress", _worker.AddressName);
Assert.False(_worker.IsRunning);
Assert.Null(_worker.LastCollectTime);
Assert.Equal(0L, _worker.SuccessCount);
Assert.Equal(0L, _worker.FailCount);
}
///
/// IsRunning_初始值_false
///
[Fact]
public void IsRunning_初始值_false()
{
CreateWorker();
Assert.False(_worker.IsRunning);
}
///
/// LastCollectTime_初始值_null
///
[Fact]
public void LastCollectTime_初始值_null()
{
CreateWorker();
Assert.Null(_worker.LastCollectTime);
}
///
/// SuccessCount_初始值_0
///
[Fact]
public void SuccessCount_初始值_0()
{
CreateWorker();
Assert.Equal(0L, _worker.SuccessCount);
}
///
/// FailCount_初始值_0
///
[Fact]
public void FailCount_初始值_0()
{
CreateWorker();
Assert.Equal(0L, _worker.FailCount);
}
///
/// Start_调用后_IsRunning变true
/// 注:Start 会启动后台线程,测试后需要 Stop
///
[Fact]
public void Start_调用后_IsRunning变true()
{
CreateWorker();
_worker.Start();
// 给予一点时间让后台线程启动
Thread.Sleep(200);
Assert.True(_worker.IsRunning);
_worker.Stop();
Thread.Sleep(100);
Assert.False(_worker.IsRunning);
}
///
/// Stop_调用后_IsRunning变false
///
[Fact]
public void Stop_调用后_IsRunning变false()
{
CreateWorker();
_worker.Stop();
Assert.False(_worker.IsRunning);
}
///
/// Start_调用两次_不崩溃
///
[Fact]
public void Start_调用两次_不崩溃()
{
CreateWorker();
_worker.Start();
Thread.Sleep(100);
// 再次调用 Start,应该不抛出异常
_worker.Start();
_worker.Stop();
Thread.Sleep(100);
Assert.False(_worker.IsRunning);
}
///
/// Stop_未启动就调用_不崩溃
///
[Fact]
public void Stop_未启动就调用_不崩溃()
{
CreateWorker();
// 直接停止,未启动状态也应稳定
_worker.Stop();
_worker.Stop();
Assert.False(_worker.IsRunning);
}
}
}