摄像机区域的架构改动
This commit is contained in:
255
Assets/Tests/EditMode/EventSystemTests.cs
Normal file
255
Assets/Tests/EditMode/EventSystemTests.cs
Normal file
@@ -0,0 +1,255 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using BaseGames.Core.Events;
|
||||
using BaseGames.Core;
|
||||
using UObject = UnityEngine.Object;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.Tests.EditMode
|
||||
{
|
||||
/// <summary>
|
||||
/// SO 事件系统 + ServiceLocator 单元测试(EditMode,无需 Play Mode)。
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class EventSystemTests
|
||||
{
|
||||
// ── EventSubscription ────────────────────────────────────────────────
|
||||
|
||||
[Test]
|
||||
public void EventSubscription_Dispose_CallsUnsubscribeAction()
|
||||
{
|
||||
bool called = false;
|
||||
var sub = new EventSubscription(() => called = true);
|
||||
sub.Dispose();
|
||||
Assert.IsTrue(called, "Dispose 应调用 unsubscribe action");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EventSubscription_Dispose_NullAction_DoesNotThrow()
|
||||
{
|
||||
var sub = new EventSubscription(null);
|
||||
Assert.DoesNotThrow(() => sub.Dispose());
|
||||
}
|
||||
|
||||
// ── CompositeDisposable ──────────────────────────────────────────────
|
||||
|
||||
[Test]
|
||||
public void CompositeDisposable_Clear_DisposesAllItems()
|
||||
{
|
||||
var composite = new CompositeDisposable();
|
||||
int count = 0;
|
||||
composite.Add(new EventSubscription(() => count++));
|
||||
composite.Add(new EventSubscription(() => count++));
|
||||
composite.Add(new EventSubscription(() => count++));
|
||||
|
||||
composite.Clear();
|
||||
Assert.AreEqual(3, count, "Clear 应 Dispose 所有已添加的订阅");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompositeDisposable_Clear_TwiceSafe()
|
||||
{
|
||||
var composite = new CompositeDisposable();
|
||||
int count = 0;
|
||||
composite.Add(new EventSubscription(() => count++));
|
||||
composite.Clear();
|
||||
composite.Clear(); // 第二次 Clear 不应重复 Dispose
|
||||
Assert.AreEqual(1, count, "Clear 两次不应重复 Dispose");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompositeDisposable_Dispose_SameAsClear()
|
||||
{
|
||||
var composite = new CompositeDisposable();
|
||||
bool disposed = false;
|
||||
composite.Add(new EventSubscription(() => disposed = true));
|
||||
((IDisposable)composite).Dispose();
|
||||
Assert.IsTrue(disposed);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddTo_ReturnsOriginalSubscription()
|
||||
{
|
||||
var composite = new CompositeDisposable();
|
||||
bool called = false;
|
||||
var sub = new EventSubscription(() => called = true);
|
||||
var returned = sub.AddTo(composite);
|
||||
returned.Dispose();
|
||||
Assert.IsTrue(called, "AddTo 返回的订阅 Dispose 后应触发原 unsubscribe");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddTo_Collection_AddsToList()
|
||||
{
|
||||
var list = new List<IDisposable>();
|
||||
bool called = false;
|
||||
var sub = new EventSubscription(() => called = true);
|
||||
sub.AddTo(list);
|
||||
Assert.AreEqual(1, list.Count, "AddTo(ICollection) 应将订阅添加到列表");
|
||||
list[0].Dispose();
|
||||
Assert.IsTrue(called);
|
||||
}
|
||||
|
||||
// ── IntEventChannelSO ────────────────────────────────────────────────
|
||||
|
||||
[Test]
|
||||
public void IntEventChannel_Raise_CallsAllSubscribers()
|
||||
{
|
||||
var channel = ScriptableObject.CreateInstance<IntEventChannelSO>();
|
||||
try
|
||||
{
|
||||
int sum = 0;
|
||||
channel.OnEventRaised += v => sum += v;
|
||||
channel.OnEventRaised += v => sum += v;
|
||||
channel.Raise(5);
|
||||
Assert.AreEqual(10, sum, "两个订阅者应各收到一次事件");
|
||||
}
|
||||
finally
|
||||
{
|
||||
UObject.DestroyImmediate(channel);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IntEventChannel_Raise_NoSubscribers_DoesNotThrow()
|
||||
{
|
||||
var channel = ScriptableObject.CreateInstance<IntEventChannelSO>();
|
||||
try
|
||||
{
|
||||
Assert.DoesNotThrow(() => channel.Raise(42));
|
||||
}
|
||||
finally
|
||||
{
|
||||
UObject.DestroyImmediate(channel);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IntEventChannel_UnsubscribeAfterDispose()
|
||||
{
|
||||
var channel = ScriptableObject.CreateInstance<IntEventChannelSO>();
|
||||
try
|
||||
{
|
||||
int callCount = 0;
|
||||
void Handler(int v) => callCount++;
|
||||
channel.OnEventRaised += Handler;
|
||||
channel.Raise(1);
|
||||
Assert.AreEqual(1, callCount);
|
||||
|
||||
channel.OnEventRaised -= Handler;
|
||||
channel.Raise(1);
|
||||
Assert.AreEqual(1, callCount, "取消订阅后不应再收到事件");
|
||||
}
|
||||
finally
|
||||
{
|
||||
UObject.DestroyImmediate(channel);
|
||||
}
|
||||
}
|
||||
|
||||
// ── VoidEventChannelSO ───────────────────────────────────────────────
|
||||
|
||||
[Test]
|
||||
public void VoidEventChannel_Raise_CallsSubscriber()
|
||||
{
|
||||
var channel = ScriptableObject.CreateInstance<VoidEventChannelSO>();
|
||||
try
|
||||
{
|
||||
bool received = false;
|
||||
channel.OnEventRaised += () => received = true;
|
||||
channel.Raise();
|
||||
Assert.IsTrue(received);
|
||||
}
|
||||
finally
|
||||
{
|
||||
UObject.DestroyImmediate(channel);
|
||||
}
|
||||
}
|
||||
|
||||
// ── ServiceLocator ───────────────────────────────────────────────────
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => ServiceLocator.Reset();
|
||||
|
||||
[TearDown]
|
||||
public void TearDown() => ServiceLocator.Reset();
|
||||
|
||||
[Test]
|
||||
public void ServiceLocator_RegisterAndGet_ReturnsInstance()
|
||||
{
|
||||
var mock = new MockService();
|
||||
ServiceLocator.Register<IMockService>(mock);
|
||||
var retrieved = ServiceLocator.Get<IMockService>();
|
||||
Assert.AreSame(mock, retrieved);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ServiceLocator_GetUnregistered_ThrowsInvalidOperation()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() => ServiceLocator.Get<IMockService>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ServiceLocator_GetOrDefault_Unregistered_ReturnsDefault()
|
||||
{
|
||||
var result = ServiceLocator.GetOrDefault<IMockService>();
|
||||
Assert.IsNull(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ServiceLocator_GetOrDefault_Registered_ReturnsInstance()
|
||||
{
|
||||
var mock = new MockService();
|
||||
ServiceLocator.Register<IMockService>(mock);
|
||||
var result = ServiceLocator.GetOrDefault<IMockService>();
|
||||
Assert.AreSame(mock, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ServiceLocator_RegisterIfAbsent_DoesNotOverwrite()
|
||||
{
|
||||
var first = new MockService();
|
||||
var second = new MockService();
|
||||
ServiceLocator.Register<IMockService>(first);
|
||||
ServiceLocator.RegisterIfAbsent<IMockService>(second);
|
||||
Assert.AreSame(first, ServiceLocator.Get<IMockService>(),
|
||||
"RegisterIfAbsent 不应覆盖已存在的注册");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ServiceLocator_Unregister_RemovesService()
|
||||
{
|
||||
ServiceLocator.Register<IMockService>(new MockService());
|
||||
ServiceLocator.Unregister<IMockService>();
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() => ServiceLocator.Get<IMockService>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ServiceLocator_Unregister_WithWrongInstance_DoesNotRemove()
|
||||
{
|
||||
var first = new MockService();
|
||||
var second = new MockService();
|
||||
ServiceLocator.Register<IMockService>(first);
|
||||
ServiceLocator.Unregister<IMockService>(second); // 不同实例,不应移除
|
||||
Assert.AreSame(first, ServiceLocator.Get<IMockService>(),
|
||||
"错误实例的 Unregister 不应移除已注册的服务");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ServiceLocator_OverrideForTest_ReplacesService()
|
||||
{
|
||||
var original = new MockService { Value = 1 };
|
||||
var replacement = new MockService { Value = 99 };
|
||||
ServiceLocator.Register<IMockService>(original);
|
||||
ServiceLocator.OverrideForTest<IMockService>(replacement);
|
||||
Assert.AreEqual(99, ServiceLocator.Get<IMockService>().Value);
|
||||
}
|
||||
|
||||
// ── Test Helpers ─────────────────────────────────────────────────────
|
||||
|
||||
private interface IMockService { int Value { get; set; } }
|
||||
private class MockService : IMockService { public int Value { get; set; } }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user