Files
FlowScope/My project/Assets/FlowScope/Tests/PlayMode/Resources/AddressablesResourceServiceTests.cs
2026-05-19 10:53:26 +08:00

104 lines
3.3 KiB
C#

using System;
using System.Collections;
using System.Threading;
using System.Threading.Tasks;
using FlowScope.Resources;
using NUnit.Framework;
using UnityEngine.TestTools;
namespace FlowScope.Tests.PlayMode.Resources
{
public sealed class AddressablesResourceServiceTests
{
[UnityTest]
public IEnumerator LoadAsync_WhenSameKeyLoadsConcurrently_SharesOneBackendLoad()
{
var backendLoads = 0;
var releaseCount = 0;
var gate = new TaskCompletionSource<object>();
var service = new AddressablesResourceService(
async (_, _, _) =>
{
backendLoads++;
return await gate.Task;
},
(_, _) => releaseCount++);
var first = service.LoadAsync<TestAsset>("shared", CancellationToken.None);
var second = service.LoadAsync<TestAsset>("shared", CancellationToken.None);
gate.SetResult(new TestAsset());
IResourceHandle<TestAsset> firstHandle = null;
IResourceHandle<TestAsset> secondHandle = null;
yield return AwaitTask(first, handle => firstHandle = handle);
yield return AwaitTask(second, handle => secondHandle = handle);
Assert.AreEqual(1, backendLoads);
Assert.AreSame(firstHandle.Asset, secondHandle.Asset);
firstHandle.Dispose();
Assert.AreEqual(0, releaseCount);
secondHandle.Dispose();
Assert.AreEqual(1, releaseCount);
}
[UnityTest]
public IEnumerator LoadAsync_WhenBackendFails_IncludesKeyAndBackend()
{
var service = new AddressablesResourceService(
(_, _, _) => throw new InvalidOperationException("missing"),
(_, _) => { });
InvalidOperationException exception = null;
yield return ThrowsAsync<InvalidOperationException>(
() => service.LoadAsync<TestAsset>("missing-key", CancellationToken.None),
caught => exception = caught);
StringAssert.Contains("missing-key", exception.Message);
StringAssert.Contains("Addressables", exception.Message);
}
private static IEnumerator ThrowsAsync<TException>(Func<Task> action, Action<TException> onCaught)
where TException : Exception
{
var task = action();
while (!task.IsCompleted)
{
yield return null;
}
if (task.IsFaulted && task.Exception?.GetBaseException() is TException exception)
{
onCaught(exception);
yield break;
}
Assert.Fail($"Expected {typeof(TException).Name}.");
}
private static IEnumerator AwaitTask<T>(Task<T> task, Action<T> onCompleted)
{
while (!task.IsCompleted)
{
yield return null;
}
if (task.IsFaulted)
{
throw task.Exception.GetBaseException();
}
if (task.IsCanceled)
{
throw new OperationCanceledException();
}
onCompleted(task.Result);
}
private sealed class TestAsset
{
}
}
}