hadashiA / VContainer

The extra fast, minimum code size, GC-free DI (Dependency Injection) library running on Unity Game Engine.
https://vcontainer.hadashikick.jp
MIT License
1.81k stars 157 forks source link

Unit Test sample #657

Closed PrarR closed 3 months ago

PrarR commented 3 months ago

I have a problem with injecting dependencies into Unit Test (Playmode), SceneManager is registered via RootSceneLifetime (Prefab), in the test I use injection via method.

During the test, I get a message that SceneManager is not set, and "Hi MM" does not appear in the console.

Any ideas how to solve this? Or some sample of how to do it correctly?

[Inject]
Private void Construct(SceneManager sceneManager)
{
    Debug.Log("Hi MM");
    _sceneManager = sceneManager;
}

obraz

PrarR commented 3 months ago

Okay, after a lot of testing, I found this solution:

        private void Construct()
        {
            var lifetimeScope = LifetimeScope.Find<RootLifetimeScope>();
            _sceneManager = lifetimeScope.Container.Resolve<SceneManager>();
        }
        [UnityTest]
        public IEnumerator ChangeSliderValue([Values(0f, 0.5f, 1f)] float value)
        {
            Construct();

            //test code...
        }

I think it would be useful to add an example of testing to the documentation, and include information about the fact that there are many valuable examples of testing in the VContainer/Assets/Tests folder.

Is it good solution or better try something else? I would appreciate feedback.

PrarR commented 3 months ago

Okay, still one problem

In the Zenject test code:

        private SignalBus _signalBus;

        private void CommonInstall()
        {
            PreInstall();
            //Container.Bind<> there
            PostInstall();

            _sceneManager = Container.Resolve<SceneManager>();
            _signalBus = Container.Resolve<SignalBus>();
        }

In desired test:

            CommonInstall();
            //test code...       

tests class inherit from ZenjectIntegrationTestFixture

Each time the test was run, the state of the Inject stuff was reset. How do I get the same result for the VContainer (without manually cleanup)?

PrarR commented 3 months ago

Okay, I did some research, I mean something like this:

https://github.com/modesttree/Zenject/blob/master/UnityProject/Assets/Plugins/Zenject/OptionalExtras/TestFramework/ZenjectIntegrationTestFixture.cs

in this class Zenject author is calling:

          ZenjectTestUtil.DestroyEverythingExceptTestRunner(immediate);

https://github.com/modesttree/Zenject/blob/master/UnityProject/Assets/Plugins/Zenject/OptionalExtras/TestFramework/ZenjectTestUtil.cs

It is really helpful to destroy everything VContainer-related in runtime (I want to test features like UI or Scenes) before next test, so I will be grateful for any tips / advices

hadashiA commented 3 months ago

If it is really unit testing, then there is no need for a DI container. If everything is written in constructor injection, the test can simply call it.

If for some reason you want to use a DI container in your tests,