If a LifetimeScope defines a parent and the parent is not found, neither a exception is thrown nor registering and resolving is executed
LifetimeScope executes in its Awake GetRuntimeParent(), which does throw a VContainerParentTypeReferenceNotFound.
However, this exception is silently handled by the Awake's try catch here and added to a waiting list.
The resulting behavior is that, when you run a scene with a LifetimeScope with a parent defined, and the parent is not found, you don't get any error or exception and you don't get neither any registering nor injection
using NUnit.Framework;
using System.Collections;
using UnityEngine;
using UnityEngine.TestTools;
using VContainer;
using VContainer.Tests.Unity;
using VContainer.Unity;
public class ParentNotFoundExceptionTest
{
private class Foo
{
public int value;
public Foo()
{
this.value = -1;
}
}
private class TestLifeTimeScope : LifetimeScope
{
public bool buildCallbackCalled = false;
public bool configureCalled = false;
protected override void Awake(){} //empty to do nothing in AddComponent
//like awake, but on demand
public void Init()
{
// this method calls to base.Awake()
// base.Awake() calls to Build
// Build to GetRuntimeParent
// GetRuntimeParent throws VContainerParentTypeReferenceNotFound
// The exception is handled in the Awake again without rethrowing
base.Awake();
}
protected override void Configure(IContainerBuilder builder)
{
configureCalled = true;
builder.RegisterBuildCallback(container =>
{
buildCallbackCalled = true;
});
builder.Register<Foo>(Lifetime.Scoped);
}
}
[UnityTest]
public IEnumerator VContainerParentTypeReferenceNotFoundTest()
{
GameObject go = new GameObject("TestLifeTimeScope");
TestLifeTimeScope testLifetimeScope = go.AddComponent<TestLifeTimeScope>();
testLifetimeScope.autoRun = true;
testLifetimeScope.parentReference = ParentReference.Create<SampleChildLifetimeScope2>();
bool exceptionThrown = false;
try
{
testLifetimeScope.Init();
}
catch (VContainerParentTypeReferenceNotFound) //parent doesn't exist, so the exception should be thrown
{
exceptionThrown = true;
}
////Expected 1. Exception thrown and registering and injection not done
//Assert.That(exceptionThrown, Is.True, "Exception not thrown");
//Assert.That(testLifetimeScope.buildCallbackCalled, Is.False, "Build Callback not called");
//Assert.That(testLifetimeScope.configureCalled, Is.False, "Configure called");
//Assert.Throws<System.NullReferenceException>(() => testLifetimeScope.Container.Resolve<Foo>());
////Expected 2. Exception not thrown and registering and injection done
//Assert.That(exceptionThrown, Is.False, "Exception not thrown");
//Assert.That(testLifetimeScope.buildCallbackCalled, Is.True, "Build Callback not called");
//Assert.That(testLifetimeScope.configureCalled, Is.True, "Configure called");
//Assert.DoesNotThrow(() => testLifetimeScope.Container.Resolve<Foo>());
//Current Behavior
Assert.That(exceptionThrown, Is.False, "Exception not thrown");
Assert.That(testLifetimeScope.buildCallbackCalled, Is.False, "Build Callback not called");
Assert.That(testLifetimeScope.configureCalled, Is.False, "Configure called");
Assert.Throws<System.NullReferenceException>(() => testLifetimeScope.Container.Resolve<Foo>());
yield return null;
}
}
If a LifetimeScope defines a parent and the parent is not found, neither a exception is thrown nor registering and resolving is executed
LifetimeScope executes in its Awake GetRuntimeParent(), which does throw a VContainerParentTypeReferenceNotFound. However, this exception is silently handled by the Awake's try catch here and added to a waiting list.
The resulting behavior is that, when you run a scene with a LifetimeScope with a parent defined, and the parent is not found, you don't get any error or exception and you don't get neither any registering nor injection
Video
https://github.com/hadashiA/VContainer/assets/25863696/ee3d6c55-5e19-41e9-ba11-9ea1b6c7d86b
Test
Scene Test
ParentNotFound.zip