using JetBrains.Annotations; using LightweightIocContainer; using LightweightIocContainer.Exceptions; using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Installers; using Moq; using NUnit.Framework; namespace Test.LightweightIocContainer { [TestFixture] public class IocContainerTest { private interface ITest { } private interface IFoo { } private class Test : ITest { } [UsedImplicitly] private class TestConstructor : ITest { public TestConstructor(string name, Test test) { } public TestConstructor(Test test, string name = null) { } public TestConstructor(IFoo foo, string name) { } } [UsedImplicitly] private class TestPrivateConstructor : ITest { private TestPrivateConstructor() { } } [UsedImplicitly] private class TestMultipleConstructors : ITest { public TestMultipleConstructors(string name, bool success) { } public TestMultipleConstructors(string name) { } } [UsedImplicitly] private class TestWithFoo : ITest { public TestWithFoo(IFoo testFoo) => TestFoo = testFoo; public IFoo TestFoo { get; } } [UsedImplicitly] private class Foo : IFoo { } [UsedImplicitly] private class FooConstructor : IFoo { public FooConstructor(string test) { } } private class MultitonScope { } private IocContainer _iocContainer; [SetUp] public void SetUp() => _iocContainer = new IocContainer(); [TearDown] public void TearDown() => _iocContainer.Dispose(); [Test] public void TestInstall() { Mock installerMock = new(); IIocContainer returnedContainer = _iocContainer.Install(installerMock.Object); installerMock.Verify(m => m.Install(It.IsAny()), Times.Once); Assert.AreEqual(_iocContainer, returnedContainer); } [Test] public void TestInstallMultiple() { Mock installer1Mock = new(); Mock installer2Mock = new(); Mock installer3Mock = new(); IIocContainer returnedContainer = _iocContainer.Install(installer1Mock.Object, installer2Mock.Object, installer3Mock.Object); installer1Mock.Verify(m => m.Install(It.IsAny()), Times.Once); installer2Mock.Verify(m => m.Install(It.IsAny()), Times.Once); installer3Mock.Verify(m => m.Install(It.IsAny()), Times.Once); Assert.AreEqual(_iocContainer, returnedContainer); } [Test] public void TestRegister() => Assert.DoesNotThrow(() => _iocContainer.Register()); [Test] public void TestRegisterTypeWithoutInterface() => Assert.DoesNotThrow(() => _iocContainer.Register()); [Test] public void TestRegisterMultiton() => Assert.DoesNotThrow(() => _iocContainer.RegisterMultiton()); [Test] public void TestInvalidMultitonRegistration() => Assert.Throws(() => _iocContainer.Register(Lifestyle.Multiton)); [Test] public void TestRegisterMultiple() { _iocContainer.Register(); MultipleRegistrationException exception = Assert.Throws(() => _iocContainer.Register()); Assert.AreEqual(typeof(ITest), exception?.Type); } [Test] public void TestResolveNotRegistered() { TypeNotRegisteredException exception = Assert.Throws(() => _iocContainer.Resolve()); Assert.AreEqual(typeof(ITest), exception?.Type); } [Test] public void TestResolve() { _iocContainer.Register(); ITest resolvedTest = _iocContainer.Resolve(); Assert.IsInstanceOf(resolvedTest); } [Test] public void TestResolveWithoutInterface() { _iocContainer.Register(); Test resolvedTest = _iocContainer.Resolve(); Assert.IsInstanceOf(resolvedTest); } [Test] public void TestResolveInterfaceWithoutImplementation() { _iocContainer.Register(); Assert.Throws(() => _iocContainer.Resolve()); } [Test] public void TestResolveImplementationRegisteredWithInterface() { _iocContainer.Register(); Test resolvedTest = _iocContainer.Resolve(); Assert.IsInstanceOf(resolvedTest); } [Test] public void TestResolveWithParams() { _iocContainer.Register(); ITest resolvedTest = _iocContainer.Resolve("Test", new Test()); Assert.IsInstanceOf(resolvedTest); } [Test] public void TestResolveWithMissingParam() { _iocContainer.Register(); _iocContainer.Register(); //this registration is abnormal and should only be used in unit tests ITest resolvedTest = _iocContainer.Resolve("Test"); Assert.IsInstanceOf(resolvedTest); } [Test] public void TestResolveSingleton() { _iocContainer.Register(Lifestyle.Singleton); ITest resolvedTest = _iocContainer.Resolve(); ITest secondResolvedTest = _iocContainer.Resolve(); Assert.AreEqual(resolvedTest, secondResolvedTest); } [Test] public void TestResolveMultiton() { _iocContainer.RegisterMultiton(); MultitonScope scope1 = new(); MultitonScope scope2 = new(); ITest resolvedTest1 = _iocContainer.Resolve(scope1); ITest resolvedTest2 = _iocContainer.Resolve(scope1); ITest resolvedTest3 = _iocContainer.Resolve(scope2); Assert.AreSame(resolvedTest1, resolvedTest2); Assert.AreNotSame(resolvedTest1, resolvedTest3); Assert.AreNotSame(resolvedTest2, resolvedTest3); } [Test] public void TestResolveMultitonNoArgs() { _iocContainer.RegisterMultiton(); MultitonResolveException exception = Assert.Throws(() => _iocContainer.Resolve()); Assert.AreEqual(typeof(ITest), exception?.Type); } [Test] public void TestResolveMultitonWrongArgs() { _iocContainer.RegisterMultiton(); MultitonResolveException exception = Assert.Throws(() => _iocContainer.Resolve(new object())); Assert.AreEqual(typeof(ITest), exception?.Type); } [Test] public void TestResolveTransient() { _iocContainer.Register(); ITest resolvedTest = _iocContainer.Resolve(); ITest secondResolvedTest = _iocContainer.Resolve(); Assert.AreNotEqual(resolvedTest, secondResolvedTest); } [Test] public void TestResolveNoMatchingConstructor() { _iocContainer.Register(); NoMatchingConstructorFoundException exception = Assert.Throws(() => _iocContainer.Resolve()); Assert.AreEqual(typeof(TestConstructor), exception?.Type); } [Test] public void TestResolveNoMatchingConstructorNotThrownWrongly() { _iocContainer.Register(); Assert.DoesNotThrow(() => _iocContainer.Resolve("Name")); } [Test] public void TestResolvePrivateConstructor() { _iocContainer.Register(); NoPublicConstructorFoundException exception = Assert.Throws(() => _iocContainer.Resolve()); Assert.AreEqual(typeof(TestPrivateConstructor), exception?.Type); } [Test] public void TestResolveSingleTypeRegistrationWithFactoryMethod() { _iocContainer.Register(); _iocContainer.Register().WithFactoryMethod(c => new TestConstructor(c.Resolve(), "someName")); ITest test = _iocContainer.Resolve(); Assert.NotNull(test); } [Test] public void TestResolveParameterIsRegisteredWithParameters() { _iocContainer.Register(); _iocContainer.Register().WithParameters("TestString"); ITest test = _iocContainer.Resolve("testName"); Assert.IsInstanceOf(test); } [Test] public void TestResolveParameterWithParameterThatIsAlreadyExistingSingleton() { _iocContainer.Register(); _iocContainer.Register(Lifestyle.Singleton).WithParameters("TestString"); IFoo foo = _iocContainer.Resolve(); ITest test = _iocContainer.Resolve("testName"); Assert.IsInstanceOf(test); Assert.AreSame(foo, ((TestWithFoo) test).TestFoo); } [Test] public void TestIsTypeRegistered() { Assert.False(_iocContainer.IsTypeRegistered()); _iocContainer.Register(); Assert.True(_iocContainer.IsTypeRegistered()); _iocContainer.Register(); Assert.True(_iocContainer.IsTypeRegistered()); } } }