// Copyright (c) 2025 EFramework Innovation. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
using NUnit.Framework;
using EFramework.Unity.MVVM;
using UnityEngine.TestTools;
using UnityEngine;
using System.Text.RegularExpressions;
///
/// TestXModule 是 XModule 的单元测试。
///
public class TestXModule
{
private enum MyModuleEventType
{
Event1,
Event2,
Event3,
Event4,
Event5,
}
private class MyModule : XModule.Base { }
private class MyInvalidModule { }
private class MySingletonModule : XModule.Base { }
private class MyModuleEventRegister
{
[XModule.Event(MyModuleEventType.Event1, typeof(MyModule), false)]
public void Func1() { }
[XModule.Event(MyModuleEventType.Event2, typeof(MyInvalidModule), true)]
protected void Func2() { }
}
private class MySubModuleEventRegister : MyModuleEventRegister
{
[XModule.Event(MyModuleEventType.Event3, typeof(MySingletonModule), false)]
public bool Func3(int a, bool b) { return false; }
[XModule.Event(MyModuleEventType.Event4, typeof(MySingletonModule), true)]
public static void Func4() { }
[XModule.Event(MyModuleEventType.Event5, null, true)]
public void Func5(object[] args) { }
}
private XModule.Base testModule;
[SetUp]
public void Setup() { testModule = new XModule.Base(); }
[TearDown]
public void Reset() { testModule = null; }
[Test]
public void Property()
{
// 验证基本属性
Assert.That(testModule.Name, Is.EqualTo(testModule.GetType().Name), "模块名称默认应当为类型名称");
testModule.name = "TestModule";
Assert.That(testModule.Name, Is.EqualTo("TestModule"), "设置name后Name属性应当正确反映");
Assert.That(testModule.Enabled, Is.False, "模块初始状态应当为未启用");
Assert.That(testModule.Event, Is.Not.Null, "模块的事件系统不应为空");
Assert.That(testModule.Tags, Is.Not.Null, "模块的标签不应为空");
Assert.That(testModule.Tags.Get("Name"), Is.EqualTo("TestModule"), "模块标签中的Name应当与模块名称一致");
Assert.That(testModule.Tags.Get("Hash"), Is.Not.Null, "模块标签中应当包含Hash值");
}
[Test]
public void Lifecycle()
{
// 验证基础生命周期方法
LogAssert.Expect(LogType.Log, new Regex(@"Module has been awaked\."));
LogAssert.Expect(LogType.Log, new Regex(@"Module has been started\."));
LogAssert.Expect(LogType.Log, new Regex(@"Module has been reseted\."));
LogAssert.Expect(LogType.Log, new Regex(@"Module has been stopped\."));
testModule.Awake();
testModule.Start();
Assert.That(testModule.Enabled, Is.True, "调用Start后模块应当处于启用状态");
testModule.Reset();
testModule.Stop();
Assert.That(testModule.Enabled, Is.False, "调用Stop后模块应当处于未启用状态");
}
[Test]
public void Event()
{
var eventTriggered = false;
void callback() => eventTriggered = true;
// 验证注册事件
testModule.Event.Register(1, callback);
testModule.Event.Notify(1);
Assert.That(eventTriggered, Is.True, "注册事件后触发通知应当调用回调函数");
// 验证注销事件
testModule.Event.Unregister(1, callback);
eventTriggered = false;
testModule.Event.Notify(1);
Assert.That(eventTriggered, Is.False, "注销事件后触发通知不应当调用回调函数");
// 验证事件特性
LogAssert.Expect(LogType.Error, new Regex(Regex.Escape("XModule.Event: unable to find instance of module TestXModule+MyModule.")));
LogAssert.Expect(LogType.Error, new Regex(Regex.Escape("XModule.Event: module TestXModule+MyInvalidModule does not implements EFramework.Unity.MVVM.XModule+IBase.")));
var events = XModule.Event.Get(typeof(MySubModuleEventRegister));
Assert.That(events.Count, Is.EqualTo(3), "MySubModuleEventRegister 类型标记的事件特性数量应为 3。");
Assert.That(events[0].ID, Is.EqualTo(MyModuleEventType.Event3.GetHashCode()), "事件特性 Func3 的事件标识应当为:{0}。", MyModuleEventType.Event3);
Assert.That(events[0].Callback.Name, Is.EqualTo("Func3"), "事件特性 Func3 应当支持带返回值及有参签名的函数。");
Assert.That(events[0].Target, Is.EqualTo(MySingletonModule.Instance), "事件特性 Func3 指定的模块实例应当和 {0} 相等。", MySingletonModule.Instance);
Assert.That(events[0].Once, Is.False, "事件特性 Func3 指定的回调一次参数应当为 {0}。", false);
Assert.That(events[1].ID, Is.EqualTo(MyModuleEventType.Event4.GetHashCode()), "事件特性 Func4 的事件标识应当为:{0}。", MyModuleEventType.Event4);
Assert.That(events[1].Callback.Name, Is.EqualTo("Func4"), "事件特性 Func4 应当支持无返回值及无参签名的静态函数。");
Assert.That(events[1].Target, Is.EqualTo(MySingletonModule.Instance), "事件特性 Func4 指定的模块实例应当和 {0} 相等。", MySingletonModule.Instance);
Assert.That(events[1].Once, Is.True, "事件特性 Func4 指定的回调一次参数应当为 {0}。", true);
Assert.That(events[2].ID, Is.EqualTo(MyModuleEventType.Event5.GetHashCode()), "事件特性 Func4 的事件标识应当为:{0}。", MyModuleEventType.Event5);
Assert.That(events[2].Callback.Name, Is.EqualTo("Func5"), "事件特性 Func5 应当支持无返回值及无参签名的静态函数。");
Assert.That(events[2].Target, Is.Null, "事件特性 Func5 指定的模块实例应当为空。");
Assert.That(events[2].Once, Is.True, "事件特性 Func5 指定的回调一次参数应当为 {0}。", true);
}
[Test]
public void Singleton()
{
// 验证单例模式
var instance1 = MySingletonModule.Instance;
var instance2 = MySingletonModule.Instance;
Assert.That(instance1, Is.Not.Null, "单例实例1不应为空");
Assert.That(instance2, Is.Not.Null, "单例实例2不应为空");
Assert.That(instance1, Is.SameAs(instance2), "两次获取的单例实例应当是同一个对象");
}
}