ResourceFull 未挂 BossResource 时改为显式抛——原先静默返回 false, 是 CLAUDE.md 第 6 条禁止的下游兜底,且与紧邻的 Boss facet 行为不一致。 FakeBossControl.DistanceToAnchor 不再忽略 index。测试改用 TearDown 清理 (本项目关闭了 Domain/Scene Reload,失败断言会把物体永久留在打开的场景里)。 BeginPhaseTransition 去掉死的默认参数;接口补充重入契约说明。 顺带去重:FakeAiContext 实现 IEnemyActor,删除两个测试内的本地 Ctx 副本 ——一个接口成员改动要同步三份是复发性成本。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
56 lines
1.8 KiB
C#
56 lines
1.8 KiB
C#
using System;
|
||
using NUnit.Framework;
|
||
using UnityEngine;
|
||
using UnityEngine.TestTools;
|
||
using BaseGames.Enemies;
|
||
|
||
namespace BaseGames.Tests.EditMode.Enemies
|
||
{
|
||
public class EnemyBrainContextBossFacetTests
|
||
{
|
||
// 本项目关闭了 Domain/Scene Reload,EditMode 测试跑在当前打开的场景上:
|
||
// 建出来的物体必须在 TearDown 里销毁,断言失败时才不会把物体永久留在场景里。
|
||
GameObject _go;
|
||
|
||
// EnemyBase.Awake 会对缺失的碰撞体/引用报错,这些与本测试无关。
|
||
[SetUp]
|
||
public void SetUp() => LogAssert.ignoreFailingMessages = true;
|
||
|
||
[TearDown]
|
||
public void TearDown()
|
||
{
|
||
LogAssert.ignoreFailingMessages = false;
|
||
if (_go != null) UnityEngine.Object.DestroyImmediate(_go);
|
||
_go = null;
|
||
}
|
||
|
||
T MakeEnemy<T>(string name) where T : EnemyBase
|
||
{
|
||
_go = new GameObject(name);
|
||
return _go.AddComponent<T>();
|
||
}
|
||
|
||
[Test]
|
||
public void NonBoss_AccessingBossFacet_Throws()
|
||
{
|
||
var enemy = MakeEnemy<EnemyBase>("plain-enemy");
|
||
var ctx = new EnemyBrainContext(enemy);
|
||
|
||
Assert.Throws<InvalidOperationException>(() => { var _ = ctx.Boss; });
|
||
}
|
||
|
||
[Test]
|
||
public void Boss_AccessingBossFacet_ReturnsTheBoss()
|
||
{
|
||
var boss = MakeEnemy<BossBase>("boss");
|
||
var ctx = new EnemyBrainContext(boss);
|
||
|
||
Assert.AreSame(boss, ctx.Boss);
|
||
Assert.AreEqual(0, ctx.Boss.CurrentPhase);
|
||
Assert.IsFalse(ctx.Boss.IsPhaseTransitioning);
|
||
// 未挂 BossResource:图查询资源满值属配置错误,必须抛而不是静默返回 false
|
||
Assert.Throws<InvalidOperationException>(() => { var _ = ctx.Boss.ResourceFull; });
|
||
}
|
||
}
|
||
}
|