feat(cordis): 接入上下文组合与模组事务热替换
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
#nullable enable
|
||||
using NUnit.Framework;
|
||||
using ShrinkApp.Starter.Basic;
|
||||
using ShrinkCommand.Integration.App;
|
||||
using ShrinkContext;
|
||||
using ShrinkDataSaver.Integration.App;
|
||||
using ShrinkNetwork;
|
||||
using ShrinkNetwork.Integration.App;
|
||||
using ShrinkApp;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace ShrinkContext.AppAdapter.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic Starter 默认装配表的端到端验证(阶段 3):
|
||||
/// 三个功能模块走原生 Cordis 组件,四个跨包集成走按键注入的薄组件;
|
||||
/// 提供者停用时依赖集成先退出,兼容服务门面也作为可逆效应注销。
|
||||
/// </summary>
|
||||
public class NativeWiringTests
|
||||
{
|
||||
[Test]
|
||||
public void BasicComposition_UsesNativeComponents_AndRetiresDependentsReversibly()
|
||||
{
|
||||
var settings = ScriptableObject.CreateInstance<ShrinkAppSettings>();
|
||||
ShrinkAppLoaderHost? host = null;
|
||||
try
|
||||
{
|
||||
host = new ShrinkAppLoaderHost(settings);
|
||||
ShrinkAppBasicContextComposition.Configure(host);
|
||||
|
||||
TestAwait.Run(host.StartAsync());
|
||||
|
||||
Assert.AreEqual(7, host.ModuleIds.Count);
|
||||
Assert.AreEqual(7, host.ActiveModuleIds.Count);
|
||||
Assert.IsTrue(host.IsModuleActive("shrink.network"));
|
||||
Assert.IsTrue(host.IsModuleActive("shrink.command"));
|
||||
Assert.IsTrue(host.IsModuleActive("shrink.datasaver"));
|
||||
Assert.IsTrue(host.IsModuleActive("shrink.integration.command-network"));
|
||||
Assert.IsTrue(host.IsModuleActive("shrink.integration.command-eventbus"));
|
||||
Assert.IsTrue(host.IsModuleActive("shrink.integration.datasaver-eventbus"));
|
||||
Assert.IsTrue(host.IsModuleActive("shrink.integration.network-eventbus"));
|
||||
|
||||
var root = host.Context.RootContext;
|
||||
Assert.IsTrue(host.Context.TryGetRaw<ShrinkNetworkService>(root,
|
||||
ShrinkNetworkAppComponent.ServiceKey, out _), "网络服务键由原生组件提供");
|
||||
Assert.IsTrue(host.Context.TryGetRaw<ShrinkCommand.ShrinkCommandService>(root,
|
||||
ShrinkCommandAppComponent.ServiceKey, out _), "命令服务键由原生组件提供");
|
||||
Assert.IsTrue(host.Context.TryGetRaw<object>(root,
|
||||
ShrinkDataSaverAppComponent.ServiceKey, out _), "存档服务键由原生组件提供");
|
||||
Assert.IsTrue(host.Context.TryGetRaw<object>(root,
|
||||
"shrink.integration.command-network", out _));
|
||||
Assert.IsTrue(host.Context.TryGetRaw<object>(root,
|
||||
"shrink.integration.command-eventbus", out _));
|
||||
Assert.IsTrue(host.Context.TryGetRaw<object>(root,
|
||||
"shrink.integration.datasaver-eventbus", out _));
|
||||
Assert.IsTrue(host.Context.TryGetRaw<object>(root,
|
||||
"shrink.integration.network-eventbus", out _));
|
||||
Assert.IsTrue(host.Services.TryGet<ShrinkNetworkAppService>(out _));
|
||||
Assert.IsTrue(host.Services.TryGet<ShrinkCommandAppService>(out _));
|
||||
Assert.IsTrue(host.Services.TryGet<ShrinkDataSaverService>(out _));
|
||||
|
||||
TestAwait.Run(host.SetModuleDisabledAsync("shrink.command", true));
|
||||
|
||||
Assert.IsFalse(host.IsModuleActive("shrink.command"));
|
||||
Assert.IsFalse(host.IsModuleActive("shrink.integration.command-network"));
|
||||
Assert.IsFalse(host.IsModuleActive("shrink.integration.command-eventbus"));
|
||||
Assert.IsTrue(host.IsModuleActive("shrink.network"), "无关提供者不得重载");
|
||||
Assert.IsTrue(host.IsModuleActive("shrink.datasaver"), "无关提供者不得重载");
|
||||
Assert.IsTrue(host.IsModuleActive("shrink.integration.network-eventbus"));
|
||||
Assert.IsTrue(host.IsModuleActive("shrink.integration.datasaver-eventbus"));
|
||||
Assert.IsFalse(host.Context.TryGetRaw<object>(root,
|
||||
ShrinkCommandAppComponent.ServiceKey, out _));
|
||||
Assert.IsFalse(host.Context.TryGetRaw<object>(root,
|
||||
"shrink.integration.command-network", out _));
|
||||
Assert.IsFalse(host.Context.TryGetRaw<object>(root,
|
||||
"shrink.integration.command-eventbus", out _));
|
||||
Assert.IsFalse(host.Services.TryGet<ShrinkCommandAppService>(out _),
|
||||
"兼容门面应随组件退役注销");
|
||||
|
||||
TestAwait.Run(host.SetModuleDisabledAsync("shrink.command", false));
|
||||
|
||||
Assert.AreEqual(7, host.ActiveModuleIds.Count);
|
||||
Assert.IsTrue(host.Services.TryGet<ShrinkCommandAppService>(out _));
|
||||
|
||||
TestAwait.Run(host.ShutdownAsync());
|
||||
Assert.AreEqual(0, host.ActiveModuleIds.Count);
|
||||
Assert.IsFalse(host.Services.TryGet<ShrinkNetworkAppService>(out _));
|
||||
Assert.IsFalse(host.Services.TryGet<ShrinkCommandAppService>(out _));
|
||||
Assert.IsFalse(host.Services.TryGet<ShrinkDataSaverService>(out _));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (host?.IsRunning == true)
|
||||
TestAwait.Run(host.ShutdownAsync());
|
||||
Object.DestroyImmediate(settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 92ef45fe59147f445bbb2ae4760732b7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,174 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using ShrinkApp;
|
||||
using ShrinkContext;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace ShrinkContext.AppAdapter.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// ShrinkApp 安装器适配器:
|
||||
/// 依赖缺失等待而非抛错(对照 ShrinkAppHost.SortInstallers 的行为差异)、
|
||||
/// 依赖就绪顺序保证、重复 ModuleId 退化为供给冲突而非宿主级失败、服务注册可见性。
|
||||
/// </summary>
|
||||
public class ShrinkAppInstallerComponentTests
|
||||
{
|
||||
private ShrinkContextRuntime _runtime = null!;
|
||||
private ShrinkAppServices _services = null!;
|
||||
private ShrinkAppSettings _settings = null!;
|
||||
private static long _sequence;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_runtime = new ShrinkContextRuntime();
|
||||
_services = new ShrinkAppServices();
|
||||
_settings = ScriptableObject.CreateInstance<ShrinkAppSettings>();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
if (_settings != null)
|
||||
Object.DestroyImmediate(_settings);
|
||||
}
|
||||
|
||||
private ShrinkFiber UseInstaller(FakeInstaller installer)
|
||||
{
|
||||
return _runtime.Use(new ShrinkAppInstallerComponent(installer, _settings), _services);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MissingDependency_WaitsInsteadOfThrowing()
|
||||
{
|
||||
var dependent = new FakeInstaller("app.b", "b-service") { DependsOn = new[] { "app.a" } };
|
||||
var fiber = UseInstaller(dependent);
|
||||
|
||||
Assert.AreEqual(ShrinkFiberState.Inactive, fiber.State,
|
||||
"依赖模块未就绪时安装器保持非活动(对照:ShrinkAppHost 在排序期直接抛依赖缺失)");
|
||||
Assert.AreEqual(0, dependent.RegisterCount);
|
||||
Assert.AreEqual(0, dependent.InitCount);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DependencyArrives_DependentActivates_AfterProvider()
|
||||
{
|
||||
var provider = new FakeInstaller("app.a", "a-service");
|
||||
var dependent = new FakeInstaller("app.b", "b-service") { DependsOn = new[] { "app.a" } };
|
||||
|
||||
var dependentFiber = UseInstaller(dependent);
|
||||
var providerFiber = UseInstaller(provider);
|
||||
|
||||
Assert.AreEqual(ShrinkFiberState.Active, providerFiber.State);
|
||||
Assert.AreEqual(ShrinkFiberState.Active, dependentFiber.State,
|
||||
"依赖键由提供者发布后,依赖安装器被响应式激活");
|
||||
|
||||
// 激活次序由依赖关系保证:提供者先完成 Register+Init
|
||||
Assert.AreEqual(1, provider.InitCount);
|
||||
Assert.AreEqual(1, dependent.InitCount);
|
||||
Assert.Less(provider.CompletedAt, dependent.CompletedAt,
|
||||
"依赖者的初始化必须晚于其依赖的提供者(空间可组合性排序)");
|
||||
|
||||
Assert.IsTrue(_services.TryGet<FakeService>(out var service));
|
||||
Assert.AreEqual("b-service", service!.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DuplicateModuleId_SecondFailsAsSupplyConflict_FirstStaysActive()
|
||||
{
|
||||
var first = new FakeInstaller("app.dup", "first");
|
||||
var second = new FakeInstaller("app.dup", "second");
|
||||
|
||||
var firstFiber = UseInstaller(first);
|
||||
var secondFiber = UseInstaller(second);
|
||||
|
||||
Assert.AreEqual(ShrinkFiberState.Active, firstFiber.State);
|
||||
Assert.AreEqual(ShrinkFiberState.Inactive, secondFiber.State);
|
||||
Assert.IsInstanceOf<ShrinkSupplyConflictException>(secondFiber.LastError,
|
||||
"重复 ModuleId 退化为该纤程的供给冲突失败,而不是宿主级异常(对照 ShrinkHost 的 Duplicate installer 抛错)");
|
||||
Assert.AreEqual(0, second.InitCount);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RetireProvider_DependentInstallerDeactivates()
|
||||
{
|
||||
var provider = new FakeInstaller("app.a", "a-service");
|
||||
var dependent = new FakeInstaller("app.b", "b-service") { DependsOn = new[] { "app.a" } };
|
||||
|
||||
var providerFiber = UseInstaller(provider);
|
||||
var dependentFiber = UseInstaller(dependent);
|
||||
Assert.AreEqual(ShrinkFiberState.Active, dependentFiber.State);
|
||||
|
||||
TestAwait.Run(_runtime.RetireAsync(providerFiber));
|
||||
|
||||
Assert.AreEqual(ShrinkFiberState.Inactive, dependentFiber.State,
|
||||
"提供者退役后依赖安装器自动停用(服务注销为已知边界,见组件注释)");
|
||||
}
|
||||
[Test]
|
||||
public void MissingServicesConfig_FailsWithClearError()
|
||||
{
|
||||
var installer = new FakeInstaller("app.x", "x");
|
||||
var component = new ShrinkAppInstallerComponent(installer, _settings);
|
||||
var fiber = _runtime.Use(component, config: null!);
|
||||
|
||||
Assert.AreEqual(ShrinkFiberState.Inactive, fiber.State);
|
||||
Assert.IsInstanceOf<InvalidOperationException>(fiber.LastError);
|
||||
StringAssert.Contains("ShrinkAppServices", fiber.LastError!.Message);
|
||||
}
|
||||
|
||||
// ---- 测试替身 ----
|
||||
|
||||
private sealed class FakeInstaller : IShrinkAppModuleInstaller
|
||||
{
|
||||
public FakeInstaller(string moduleId, string serviceValue)
|
||||
{
|
||||
ModuleId = moduleId;
|
||||
ServiceValue = serviceValue;
|
||||
}
|
||||
|
||||
public string ModuleId { get; }
|
||||
public int Order => 0;
|
||||
public IReadOnlyList<string> DependsOn { get; set; } = Array.Empty<string>();
|
||||
public int RegisterCount { get; private set; }
|
||||
public int InitCount { get; private set; }
|
||||
public long CompletedAt { get; private set; }
|
||||
private string ServiceValue { get; }
|
||||
|
||||
public void RegisterServices(ShrinkAppContext context)
|
||||
{
|
||||
RegisterCount++;
|
||||
context.Services.Register(new FakeService(ServiceValue));
|
||||
}
|
||||
|
||||
public UniTask InitializeAsync(ShrinkAppContext context)
|
||||
{
|
||||
InitCount++;
|
||||
CompletedAt = ++_sequence;
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FakeService
|
||||
{
|
||||
public FakeService(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public string Value { get; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>跨程序集测试辅助(与 ShrinkContext.Core.Tests.TestAwait 同语义)。</summary>
|
||||
public static class TestAwait
|
||||
{
|
||||
public static void Run(UniTask task)
|
||||
{
|
||||
task.GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4351747efa1ed6242a67b18f60388935
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,205 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using ShrinkApp;
|
||||
using ShrinkContext;
|
||||
using ShrinkEventBus;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace ShrinkContext.AppAdapter.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// ShrinkAppLoaderHost 端到端:
|
||||
/// 启动激活与 Started 事件、运行中 disable/enable 不重启宿主、设置级初始禁用、
|
||||
/// 未知模块报错、重复 ModuleId 构造期失败、Shutdown。
|
||||
/// </summary>
|
||||
public class ShrinkAppLoaderHostTests
|
||||
{
|
||||
private ShrinkAppSettings _settings = null!;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_settings = ScriptableObject.CreateInstance<ShrinkAppSettings>();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
if (_settings != null)
|
||||
Object.DestroyImmediate(_settings);
|
||||
}
|
||||
|
||||
private ShrinkAppLoaderHost CreateHost(params FakeInstaller[] installers)
|
||||
{
|
||||
return new ShrinkAppLoaderHost(_settings, installers);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StartAsync_ActivatesModules_AndPublishesStartedEvent()
|
||||
{
|
||||
var host = CreateHost(
|
||||
new FakeInstaller("app.a", "a"),
|
||||
new FakeInstaller("app.b", "b") { DependsOn = new[] { "app.a" } });
|
||||
|
||||
ShrinkAppStartedEvent? started = null;
|
||||
using (var subscription = EventBus.SubscribeEvent<ShrinkAppStartedEvent>(e => started = e))
|
||||
{
|
||||
TestAwait.Run(host.StartAsync());
|
||||
}
|
||||
|
||||
Assert.IsTrue(host.IsRunning);
|
||||
Assert.IsTrue(host.IsModuleActive("app.a"));
|
||||
Assert.IsTrue(host.IsModuleActive("app.b"), "依赖模块在提供者激活后自动激活");
|
||||
Assert.IsNotNull(started);
|
||||
CollectionAssert.AreEquivalent(new[] { "app.a", "app.b" }, started!.ModuleIds);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetModuleDisabled_RetiresModuleAndDependents_EnableReloadsWithoutRestart()
|
||||
{
|
||||
var provider = new FakeInstaller("app.a", "a");
|
||||
var dependent = new FakeInstaller("app.b", "b") { DependsOn = new[] { "app.a" } };
|
||||
var bystander = new FakeInstaller("app.c", "c");
|
||||
var host = CreateHost(provider, dependent, bystander);
|
||||
TestAwait.Run(host.StartAsync());
|
||||
Assert.AreEqual(3, host.ActiveModuleIds.Count);
|
||||
|
||||
TestAwait.Run(host.SetModuleDisabledAsync("app.a", true));
|
||||
|
||||
Assert.IsTrue(host.IsModuleDisabled("app.a"));
|
||||
Assert.IsFalse(host.IsModuleActive("app.a"));
|
||||
Assert.IsFalse(host.IsModuleActive("app.b"), "依赖者随提供者停用");
|
||||
Assert.IsTrue(host.IsModuleActive("app.c"), "无关模块不受影响,宿主不重启");
|
||||
Assert.IsTrue(host.IsRunning);
|
||||
|
||||
TestAwait.Run(host.SetModuleDisabledAsync("app.a", false));
|
||||
|
||||
Assert.IsTrue(host.IsModuleActive("app.a"));
|
||||
Assert.IsTrue(host.IsModuleActive("app.b"), "重新启用后依赖链整体复活");
|
||||
Assert.AreEqual(2, provider.InitCount, "重启用会重新执行安装器初始化(重建语义)");
|
||||
Assert.AreEqual(1, bystander.InitCount, "未受影响的模块不重复初始化");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisabledViaSettings_ExcludedInitially_CanEnableAtRuntime()
|
||||
{
|
||||
_settings.disabledModuleIds = new[] { "app.a" };
|
||||
var provider = new FakeInstaller("app.a", "a");
|
||||
var dependent = new FakeInstaller("app.b", "b") { DependsOn = new[] { "app.a" } };
|
||||
var host = CreateHost(provider, dependent);
|
||||
|
||||
TestAwait.Run(host.StartAsync());
|
||||
|
||||
Assert.IsTrue(host.IsModuleDisabled("app.a"));
|
||||
Assert.IsFalse(host.TryGetModuleFiber("app.a", out _));
|
||||
Assert.IsTrue(host.IsModuleWaiting("app.b"), "依赖被禁用模块的安装器保持等待而非报错");
|
||||
CollectionAssert.AreEqual(new[] { "app.b" }, host.WaitingModuleIds);
|
||||
|
||||
TestAwait.Run(host.SetModuleDisabledAsync("app.a", false));
|
||||
Assert.IsTrue(host.IsModuleActive("app.a"));
|
||||
Assert.IsTrue(host.IsModuleActive("app.b"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnknownModuleId_Throws()
|
||||
{
|
||||
var host = CreateHost(new FakeInstaller("app.a", "a"));
|
||||
TestAwait.Run(host.StartAsync());
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
TestAwait.Run(host.SetModuleDisabledAsync("app.no-such", true)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DuplicateModuleIds_ThrowAtConstruction()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
CreateHost(new FakeInstaller("app.dup", "a"), new FakeInstaller("app.dup", "b")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShutdownAsync_RetiresEverything()
|
||||
{
|
||||
var provider = new FakeInstaller("app.a", "a");
|
||||
var host = CreateHost(provider);
|
||||
TestAwait.Run(host.StartAsync());
|
||||
Assert.IsTrue(host.IsModuleActive("app.a"));
|
||||
|
||||
TestAwait.Run(host.ShutdownAsync());
|
||||
|
||||
Assert.IsFalse(host.IsRunning);
|
||||
Assert.IsFalse(host.IsModuleActive("app.a"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OverrideModuleComponent_ReplacesInstallerWrapper()
|
||||
{
|
||||
var installer = new FakeInstaller("app.a", "a");
|
||||
var host = CreateHost(installer);
|
||||
host.OverrideModuleComponent("app.a", () => new NativeReplacementComponent());
|
||||
|
||||
TestAwait.Run(host.StartAsync());
|
||||
|
||||
Assert.IsTrue(host.IsModuleActive("app.a"));
|
||||
Assert.AreEqual(0, installer.InitCount, "原生组件替换后安装器不再被包装执行");
|
||||
Assert.IsTrue(host.TryGetModuleFiber("app.a", out var fiber));
|
||||
Assert.IsInstanceOf<NativeReplacementComponent>(fiber.Component);
|
||||
}
|
||||
|
||||
/// <summary>替换安装器的原生测试组件(发布同一模块键)。</summary>
|
||||
private sealed class NativeReplacementComponent : IShrinkComponent
|
||||
{
|
||||
public string Name => "app.a";
|
||||
public System.Collections.Generic.IReadOnlyList<string> Inject => System.Array.Empty<string>();
|
||||
public System.Collections.Generic.IReadOnlyList<string> Provide =>
|
||||
new[] { ShrinkAppInstallerComponent.ModuleKeyPrefix + "app.a" };
|
||||
|
||||
public UniTask ApplyAsync(ShrinkCtx ctx, object? config)
|
||||
{
|
||||
ctx.Set(Provide[0], Name);
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FakeInstaller : IShrinkAppModuleInstaller
|
||||
{
|
||||
public FakeInstaller(string moduleId, string serviceValue)
|
||||
{
|
||||
ModuleId = moduleId;
|
||||
ServiceValue = serviceValue;
|
||||
}
|
||||
|
||||
public string ModuleId { get; }
|
||||
public int Order => 0;
|
||||
public IReadOnlyList<string> DependsOn { get; set; } = Array.Empty<string>();
|
||||
public int InitCount { get; private set; }
|
||||
private string ServiceValue { get; }
|
||||
|
||||
public void RegisterServices(ShrinkAppContext context)
|
||||
{
|
||||
context.Services.Register(new FakeService(ServiceValue));
|
||||
}
|
||||
|
||||
public UniTask InitializeAsync(ShrinkAppContext context)
|
||||
{
|
||||
InitCount++;
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FakeService
|
||||
{
|
||||
public FakeService(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public string Value { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4aa1105e16f405b428d2c5a841521479
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "ShrinkContext.AppAdapter.Tests",
|
||||
"rootNamespace": "ShrinkContext.AppAdapter.Tests",
|
||||
"references": [
|
||||
"ShrinkContext.AppAdapter.Runtime",
|
||||
"ShrinkContext.Core.Runtime",
|
||||
"ShrinkApp.Core.Runtime",
|
||||
"ShrinkApp.Starter.Basic.Runtime",
|
||||
"ShrinkEventBus.Runtime",
|
||||
"ShrinkNetwork.Integration.App",
|
||||
"ShrinkCommand.Integration.App",
|
||||
"ShrinkDataSaver.Integration.App",
|
||||
"ShrinkNetwork.Runtime",
|
||||
"ShrinkCommand.Runtime",
|
||||
"UniTask",
|
||||
"UnityEngine.TestRunner",
|
||||
"UnityEditor.TestRunner"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 907201a93f40ce44781eaa942ed9dbac
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user