mirror of https://github.com/AMT-Cheif/Stylet.git
Add some unit tests
This commit is contained in:
parent
a1c4c12030
commit
3246f5db29
|
@ -60,7 +60,8 @@ namespace StyletIoC
|
|||
if (!this.parentDictionary.TryGetValue(key, out tempValue))
|
||||
return false;
|
||||
|
||||
this.ourDictionary.TryAdd(key, this.translator(tempValue));
|
||||
value = this.translator(tempValue);
|
||||
this.ourDictionary.TryAdd(key, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,6 @@ namespace StyletIoC
|
|||
|
||||
internal class SingletonRegistration : RegistrationBase
|
||||
{
|
||||
private object instance;
|
||||
private Expression instanceExpression;
|
||||
private readonly IRegistrationContext parentContext;
|
||||
|
||||
|
@ -90,25 +89,15 @@ namespace StyletIoC
|
|||
this.parentContext = parentContext;
|
||||
}
|
||||
|
||||
private void EnsureInstantiated(ParameterExpression registrationContext)
|
||||
{
|
||||
if (this.instance != null)
|
||||
return;
|
||||
|
||||
// Ensure we don't end up creating two singletons, one used by each thread
|
||||
var instance = Expression.Lambda<Func<IRegistrationContext, object>>(this.creator.GetInstanceExpression(registrationContext), registrationContext).Compile()(this.parentContext);
|
||||
Interlocked.CompareExchange(ref this.instance, instance, null);
|
||||
}
|
||||
|
||||
public override Expression GetInstanceExpression(ParameterExpression registrationContext)
|
||||
{
|
||||
if (this.instanceExpression != null)
|
||||
return this.instanceExpression;
|
||||
|
||||
this.EnsureInstantiated(registrationContext);
|
||||
var instance = Expression.Lambda<Func<IRegistrationContext, object>>(this.creator.GetInstanceExpression(registrationContext), registrationContext).Compile()(this.parentContext);
|
||||
|
||||
// This expression yields the actual type of instance, not 'object'
|
||||
var instanceExpression = Expression.Constant(this.instance);
|
||||
var instanceExpression = Expression.Constant(instance);
|
||||
Interlocked.CompareExchange(ref this.instanceExpression, instanceExpression, null);
|
||||
return this.instanceExpression;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace StyletIoC
|
|||
/// </summary>
|
||||
/// <typeparam name="TImplementation">Type returned by the factory delegate. Must implement the service</typeparam>
|
||||
/// <param name="factory">Factory delegate to bind got</param>
|
||||
IInScopeOrWithKey ToFactory<TImplementation>(Func<IContainer, TImplementation> factory);
|
||||
IInScopeOrWithKey ToFactory<TImplementation>(Func<IRegistrationContext, TImplementation> factory);
|
||||
|
||||
/// <summary>
|
||||
/// If the service is an interface with a number of methods which return other types, generate an implementation of that abstract factory and bind it to the interface.
|
||||
|
@ -128,7 +128,7 @@ namespace StyletIoC
|
|||
return this.builderBinding;
|
||||
}
|
||||
|
||||
public IInScopeOrWithKey ToFactory<TImplementation>(Func<IContainer, TImplementation> factory)
|
||||
public IInScopeOrWithKey ToFactory<TImplementation>(Func<IRegistrationContext, TImplementation> factory)
|
||||
{
|
||||
this.builderBinding = new BuilderFactoryBinding<TImplementation>(this.ServiceType, factory);
|
||||
return this.builderBinding;
|
||||
|
@ -261,9 +261,9 @@ namespace StyletIoC
|
|||
|
||||
internal class BuilderFactoryBinding<TImplementation> : BuilderBindingBase
|
||||
{
|
||||
private Func<IContainer, TImplementation> factory;
|
||||
private Func<IRegistrationContext, TImplementation> factory;
|
||||
|
||||
public BuilderFactoryBinding(Type serviceType, Func<IContainer, TImplementation> factory) : base(serviceType)
|
||||
public BuilderFactoryBinding(Type serviceType, Func<IRegistrationContext, TImplementation> factory) : base(serviceType)
|
||||
{
|
||||
if (this.serviceType.IsGenericTypeDefinition)
|
||||
throw new StyletIoCRegistrationException(String.Format("A factory cannot be used to implement unbound generic type {0}", this.serviceType.Description()));
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
using NUnit.Framework;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletUnitTests.StyletIoC
|
||||
{
|
||||
[TestFixture]
|
||||
public class StyletIoCChildContainerTests
|
||||
{
|
||||
class C1 { }
|
||||
class C2
|
||||
{
|
||||
public C1 C1;
|
||||
public C2(C1 c1) { this.C1 = c1; }
|
||||
}
|
||||
class C3
|
||||
{
|
||||
public bool C1CtorCalled;
|
||||
public bool NoArgsCtorCalled;
|
||||
|
||||
public C3(C1 c2)
|
||||
{
|
||||
this.C1CtorCalled = true;
|
||||
}
|
||||
public C3()
|
||||
{
|
||||
this.NoArgsCtorCalled = true;
|
||||
}
|
||||
}
|
||||
class C4<T> { }
|
||||
interface IValidator<T> { }
|
||||
class StringValidator : IValidator<string> { }
|
||||
class IntValidator : IValidator<int> { }
|
||||
|
||||
[Test]
|
||||
public void ChildContainerCanAccessRegistrationsOnParent()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<C1>().ToSelf();
|
||||
builder.Bind<C2>().ToSelf();
|
||||
var parent = builder.BuildContainer();
|
||||
var child = parent.CreateChildBuilder().BuildContainer();
|
||||
|
||||
var c2 = child.Get<C2>();
|
||||
Assert.NotNull(c2);
|
||||
Assert.NotNull(c2.C1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ChildContainerSharesParentSingletons()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<C1>().ToSelf().InSingletonScope();
|
||||
var parent = builder.BuildContainer();
|
||||
var child = parent.CreateChildBuilder().BuildContainer();
|
||||
|
||||
Assert.AreEqual(parent.Get<C1>(), child.Get<C1>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ChildContainersDontShareSingletons()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
var parent = builder.BuildContainer();
|
||||
var child1Builder = parent.CreateChildBuilder();
|
||||
child1Builder.Bind<C1>().ToSelf().InSingletonScope();
|
||||
var child1 = child1Builder.BuildContainer();
|
||||
var child2Builder = parent.CreateChildBuilder();
|
||||
child2Builder.Bind<C1>().ToSelf().InSingletonScope();
|
||||
var child2 = child2Builder.BuildContainer();
|
||||
|
||||
Assert.AreNotEqual(child1.Get<C1>(), child2.Get<C1>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ResolvingOnParentDoesNotTakeChildIntoAccount_CalledFromChild()
|
||||
{
|
||||
// It will have to pick the C3 ctor which doesn't require C1, as C1 exists only in the child
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<C3>().ToSelf();
|
||||
var parent = builder.BuildContainer();
|
||||
|
||||
var childBuilder = parent.CreateChildBuilder();
|
||||
childBuilder.Bind<C1>().ToSelf();
|
||||
var child = childBuilder.BuildContainer();
|
||||
|
||||
// Compile it in the context of the child, first
|
||||
var c3 = child.Get<C3>();
|
||||
Assert.IsTrue(c3.NoArgsCtorCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ResolvingOnParentDoesNotTakeChildIntoAccount_CalledFromParent()
|
||||
{
|
||||
// It will have to pick the C3 ctor which doesn't require C1, as C1 exists only in the child
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<C3>().ToSelf();
|
||||
var parent = builder.BuildContainer();
|
||||
|
||||
var childBuilder = parent.CreateChildBuilder();
|
||||
childBuilder.Bind<C1>().ToSelf();
|
||||
var child = childBuilder.BuildContainer();
|
||||
|
||||
// Now compile from the parent
|
||||
var c3 = parent.Get<C3>();
|
||||
Assert.IsTrue(c3.NoArgsCtorCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RegistrationsOnChildDoNotAffectParent()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<C1>().ToSelf();
|
||||
var parent = builder.BuildContainer();
|
||||
|
||||
var childBuilder = parent.CreateChildBuilder();
|
||||
childBuilder.Bind<C2>().ToSelf();
|
||||
var child = childBuilder.BuildContainer();
|
||||
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => parent.Get<C2>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RecreatingSingletonBindingIntroducedNewScope()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<C1>().ToSelf().InSingletonScope();
|
||||
var parent = builder.BuildContainer();
|
||||
|
||||
var childBuilder = parent.CreateChildBuilder();
|
||||
childBuilder.Bind<C1>().ToSelf().InSingletonScope();
|
||||
var child = childBuilder.BuildContainer();
|
||||
|
||||
Assert.AreNotEqual(parent.Get<C1>(), child.Get<C1>());
|
||||
Assert.AreEqual(parent.Get<C1>(), parent.Get<C1>());
|
||||
Assert.AreEqual(child.Get<C1>(), child.Get<C1>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FactoriesResolveUsingTheResolutionContextOnWhichTheyWereRequested()
|
||||
{
|
||||
IRegistrationContext factoryContext = null;
|
||||
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<C1>().ToFactory(c =>
|
||||
{
|
||||
factoryContext = c;
|
||||
return new C1();
|
||||
});
|
||||
var parent = builder.BuildContainer();
|
||||
|
||||
var child = parent.CreateChildBuilder().BuildContainer();
|
||||
|
||||
parent.Get<C1>();
|
||||
Assert.AreEqual(parent, factoryContext);
|
||||
|
||||
child.Get<C1>();
|
||||
Assert.AreEqual(child, factoryContext);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ChildInheritsParentsUnboundGenerics()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind(typeof(C4<>)).ToSelf();
|
||||
var parent = builder.BuildContainer();
|
||||
|
||||
var child = parent.CreateChildBuilder().BuildContainer();
|
||||
|
||||
Assert.IsInstanceOf<C4<int>>(child.Get<C4<int>>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ChildInheritsParentsBoundGenerics()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<IValidator<string>>().To<StringValidator>();
|
||||
var parent = builder.BuildContainer();
|
||||
|
||||
var childBuilder = parent.CreateChildBuilder();
|
||||
childBuilder.Bind<IValidator<int>>().To<IntValidator>();
|
||||
var child = childBuilder.BuildContainer();
|
||||
|
||||
Assert.DoesNotThrow(() => child.Get<IValidator<string>>());
|
||||
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => parent.Get<IValidator<int>>());
|
||||
Assert.DoesNotThrow(() => child.Get<IValidator<int>>());
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => parent.Get<IValidator<int>>());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -65,6 +65,7 @@
|
|||
<Compile Include="ConductorOneActiveTests.cs" />
|
||||
<Compile Include="ConductorTests.cs" />
|
||||
<Compile Include="DebugConverterTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCChildContainerTests.cs" />
|
||||
<Compile Include="TraceLoggerTests.cs" />
|
||||
<Compile Include="EqualityConverterTests.cs" />
|
||||
<Compile Include="EventActionTests.cs" />
|
||||
|
|
Loading…
Reference in New Issue