using GFramework.Core.property; using NUnit.Framework; namespace GFramework.Core.Tests.property; /// /// BindableProperty类的单元测试 /// [TestFixture] public class BindablePropertyTests { /// /// 测试清理方法,在每个测试方法执行后重置比较器 /// [TearDown] public void TearDown() { BindableProperty.Comparer = (a, b) => a?.Equals(b) ?? b == null; } /// /// 测试获取值时应返回默认值 /// [Test] public void Value_Get_Should_Return_Default_Value() { var property = new BindableProperty(5); Assert.That(property.Value, Is.EqualTo(5)); } /// /// 测试设置值时应触发事件 /// [Test] public void Value_Set_Should_Trigger_Event() { var property = new BindableProperty(); var receivedValue = 0; property.Register(value => { receivedValue = value; }); property.Value = 42; Assert.That(receivedValue, Is.EqualTo(42)); } /// /// 测试设置相同值时不触发事件 /// [Test] public void Value_Set_To_Same_Value_Should_Not_Trigger_Event() { var property = new BindableProperty(5); var count = 0; property.Register(_ => { count++; }); property.Value = 5; Assert.That(count, Is.EqualTo(0)); } /// /// 测试取消注册应移除处理器 /// [Test] public void UnRegister_Should_Remove_Handler() { var property = new BindableProperty(); var count = 0; Action handler = _ => { count++; }; property.Register(handler); property.Value = 1; Assert.That(count, Is.EqualTo(1)); property.UnRegister(handler); property.Value = 2; Assert.That(count, Is.EqualTo(1)); } /// /// 测试带初始值注册应立即调用处理器 /// [Test] public void RegisterWithInitValue_Should_Call_Handler_Immediately() { var property = new BindableProperty(5); var receivedValue = 0; property.RegisterWithInitValue(value => { receivedValue = value; }); Assert.That(receivedValue, Is.EqualTo(5)); } /// /// 测试无事件设置值不应触发事件 /// [Test] public void SetValueWithoutEvent_Should_Not_Trigger_Event() { var property = new BindableProperty(); var count = 0; property.Register(_ => { count++; }); property.SetValueWithoutEvent(42); Assert.That(count, Is.EqualTo(0)); Assert.That(property.Value, Is.EqualTo(42)); } /// /// 测试使用自定义比较器 /// [Test] public void WithComparer_Should_Use_Custom_Comparer() { var comparerWasCalled = false; var comparisonResult = false; // 设置自定义比较器 BindableProperty.Comparer = (a, b) => { comparerWasCalled = true; comparisonResult = a.Length == b.Length; return comparisonResult; }; var property = new BindableProperty("test"); var count = 0; property.Register(_ => { count++; }); property.Value = "test"; Assert.That(comparerWasCalled, Is.True, "自定义比较器应该被调用"); Assert.That(comparisonResult, Is.True, "比较结果应该是true(相同长度)"); Assert.That(count, Is.EqualTo(0), "不应该触发事件"); } /// /// 测试多个处理器都应被调用 /// [Test] public void Multiple_Handlers_Should_All_Be_Called() { var property = new BindableProperty(); var count1 = 0; var count2 = 0; property.Register(_ => { count1++; }); property.Register(_ => { count2++; }); property.Value = 42; Assert.That(count1, Is.EqualTo(1)); Assert.That(count2, Is.EqualTo(1)); } /// /// 测试注册应返回IUnRegister接口 /// [Test] public void Register_Should_Return_IUnRegister() { var property = new BindableProperty(); var unRegister = property.Register(_ => { }); Assert.That(unRegister, Is.Not.Null); } /// /// 测试ToString应返回值的字符串表示 /// [Test] public void ToString_Should_Return_Value_As_String() { var property = new BindableProperty(42); var result = property.ToString(); Assert.That(result, Is.EqualTo("42")); } /// /// 测试并发场景下的属性值设置 /// [Test] public void Concurrent_Value_Set_Should_Be_Thread_Safe() { var property = new BindableProperty(0); const int threadCount = 10; const int iterationsPerThread = 100; var tasks = new Task[threadCount]; var exceptions = new List(); for (var i = 0; i < threadCount; i++) { var threadId = i; tasks[i] = Task.Run(() => { try { for (var j = 0; j < iterationsPerThread; j++) { property.Value = threadId * iterationsPerThread + j; } } catch (Exception ex) { lock (exceptions) { exceptions.Add(ex); } } }); } Task.WaitAll(tasks); Assert.That(exceptions, Is.Empty, $"并发测试中发生异常: {string.Join(", ", exceptions.Select(e => e.Message))}"); } /// /// 测试并发场景下的事件注册和触发 /// [Test] public void Concurrent_Register_And_Trigger_Should_Be_Thread_Safe() { var property = new BindableProperty(0); const int threadCount = 5; var tasks = new Task[threadCount]; var exceptions = new List(); var callCounts = new int[threadCount]; for (var i = 0; i < threadCount; i++) { var threadId = i; tasks[i] = Task.Run(() => { try { property.Register(value => { Interlocked.Increment(ref callCounts[threadId]); }); } catch (Exception ex) { lock (exceptions) { exceptions.Add(ex); } } }); } Task.WaitAll(tasks); // 触发事件 property.Value = 42; Assert.That(exceptions, Is.Empty); Assert.That(callCounts.Sum(), Is.EqualTo(threadCount), "所有注册的处理器都应该被调用"); } /// /// 测试并发场景下的注册和取消注册 /// [Test] public void Concurrent_Register_And_UnRegister_Should_Be_Thread_Safe() { var property = new BindableProperty(0); const int threadCount = 10; const int iterationsPerThread = 50; var tasks = new Task[threadCount]; var exceptions = new List(); for (var i = 0; i < threadCount; i++) { tasks[i] = Task.Run(() => { try { for (var j = 0; j < iterationsPerThread; j++) { Action handler = _ => { }; property.Register(handler); property.UnRegister(handler); } } catch (Exception ex) { lock (exceptions) { exceptions.Add(ex); } } }); } Task.WaitAll(tasks); Assert.That(exceptions, Is.Empty); } /// /// 测试并发场景下RegisterWithInitValue的线程安全性 /// [Test] public void Concurrent_RegisterWithInitValue_Should_Be_Thread_Safe() { var property = new BindableProperty(42); const int threadCount = 10; var tasks = new Task[threadCount]; var exceptions = new List(); var receivedValues = new List(); for (var i = 0; i < threadCount; i++) { tasks[i] = Task.Run(() => { try { property.RegisterWithInitValue(value => { lock (receivedValues) { receivedValues.Add(value); } }); } catch (Exception ex) { lock (exceptions) { exceptions.Add(ex); } } }); } Task.WaitAll(tasks); Assert.That(exceptions, Is.Empty); Assert.That(receivedValues.Count, Is.EqualTo(threadCount)); Assert.That(receivedValues.All(v => v == 42), Is.True, "所有初始值都应该是42"); } }