Hi folks. I'm currently enjoying the AutoMockingContainer found in
RhinoTesting (although a binary download against the current released
dlls would be nice).
I'm missing support for non-public constructors. I want to write code
that has a default constructor that provides the dependencies to an
internal constructor. In production code, I use the default
constructor. In test code, I use the internal constructor. The current
AutoMockingContainer doesn't know how to handle this usage - it only
works with public constructors.
This patch allows for internal (and even private!) constructors. Hope
the paste works:
Index: Rhino.Testing.Tests/AutoMocking/AddComponentInstanceFixture.cs
===================================================================
--- Rhino.Testing.Tests/AutoMocking/AddComponentInstanceFixture.cs
(revision 1715)
+++ Rhino.Testing.Tests/AutoMocking/AddComponentInstanceFixture.cs
(working copy)
@@ -1,31 +1,34 @@
using MbUnit.Framework;
-using Rhino.Mocks;
-using Rhino.Testing.AutoMocking;
-
-[TestFixture]
-public class AddComponentInstanceFixture
-{
- private AutoMockingContainer container;
- private MockRepository mocks;
-
- public class InstancedComponent
- {
- }
-
- [SetUp]
- public void SetUp()
- {
- mocks = new MockRepository();
- container = new AutoMockingContainer(mocks);
- container.Initialize();
- }
-
-
- [Test]
- public void AddComponentInstance_CanBeRetrieved()
- {
- InstancedComponent component = new InstancedComponent();
- container.Kernel.AddComponentInstance("InstancedComponent",
typeof
(InstancedComponent), component);
- Assert.AreEqual(component, container.Get<InstancedComponent>());
- }
+using Rhino.Mocks;
+using Rhino.Testing.AutoMocking;
+
+namespace Rhino.Testing.Tests.AutoMocking
+{
+ [TestFixture]
+ public class AddComponentInstanceFixture
+ {
+ private AutoMockingContainer container;
+ private MockRepository mocks;
+
+ public class InstancedComponent
+ {
+ }
+
+ [SetUp]
+ public void SetUp()
+ {
+ mocks = new MockRepository();
+ container = new AutoMockingContainer(mocks);
+ container.Initialize();
+ }
+
+
+ [Test]
+ public void AddComponentInstance_CanBeRetrieved()
+ {
+ InstancedComponent component = new InstancedComponent();
+
container.Kernel.AddComponentInstance("InstancedComponent",
typeof(InstancedComponent), component);
+ Assert.AreEqual(component,
container.Get<InstancedComponent>());
+ }
+ }
}
\ No newline at end of file
Index: Rhino.Testing.Tests/AutoMocking/AutoMockingContainerTests.cs
===================================================================
--- Rhino.Testing.Tests/AutoMocking/AutoMockingContainerTests.cs
(revision 1715)
+++ Rhino.Testing.Tests/AutoMocking/AutoMockingContainerTests.cs
(working copy)
@@ -27,7 +27,40 @@
}
- [Test]
+ // It might be nice to test this on a class in a separate
assembly...
+ [Test]
+ public void
Create_WillResolveDependenciesOnInternalClassWithInternalConstructor()
+ {
+ InternalComponentBeingConfigured target =
container.Create<InternalComponentBeingConfigured>();
+ Assert.IsNotNull(target.ReallyCoolService, "mocked
ReallyCoolService dependency");
+ Assert.IsNotNull(target.Services, "mocked Services
dependency");
+ }
+
+ [Test]
+ public void
Create_WillResolveDependenciesPreferringInternalConstructor()
+ {
+ ComponentBeingConfiguredWithInternalCtor target =
container.Create<ComponentBeingConfiguredWithInternalCtor>();
+ Assert.IsNotNull(target.ReallyCoolService, "mocked
ReallyCoolService dependency");
+ Assert.IsNotNull(target.Services, "mocked Services
dependency");
+ }
+
+ [Test]
+ public void
Create_WillResolveDependenciesPreferringInternalConstructor_WithResolvePropertiesEnabled()
+ {
+ ComponentBeingConfiguredWithInternalCtor target =
containerThatResolvesProperties.Create<ComponentBeingConfiguredWithInternalCtor>();
+ Assert.IsNotNull(target.ReallyCoolService, "mocked
ReallyCoolService dependency");
+ Assert.IsNotNull(target.Services, "mocked Services
dependency");
+ }
+
+ [Test]
+ public void
Create_WillResolveDependenciesPreferringPrivateConstructor()
+ {
+ ComponentBeingConfiguredWithPrivateCtor target =
container.Create<ComponentBeingConfiguredWithPrivateCtor>();
+ Assert.IsNotNull(target.ReallyCoolService, "mocked
ReallyCoolService dependency");
+ Assert.IsNotNull(target.Services, "mocked Services
dependency");
+ }
+
+ [Test]
public void Create_WillResolveDependenciesAsMocks_ByDefault()
{
ComponentBeingConfigured target =
container.Create<ComponentBeingConfigured>();
Index: Rhino.Testing.Tests/AutoMocking/ComponentBeingConfigured.cs
===================================================================
--- Rhino.Testing.Tests/AutoMocking/ComponentBeingConfigured.cs
(revision 1715)
+++ Rhino.Testing.Tests/AutoMocking/ComponentBeingConfigured.cs
(working copy)
@@ -11,7 +11,6 @@
Services = services;
}
-
public ComponentBeingConfigured(IReallyCoolService
reallyCoolService)
{
ReallyCoolService = reallyCoolService;
Index: Rhino.Testing.Tests/AutoMocking/
ComponentBeingConfiguredWithInternalCtor.cs
===================================================================
--- Rhino.Testing.Tests/AutoMocking/
ComponentBeingConfiguredWithInternalCtor.cs (revision 0)
+++ Rhino.Testing.Tests/AutoMocking/
ComponentBeingConfiguredWithInternalCtor.cs (revision 0)
@@ -0,0 +1,24 @@
+namespace Rhino.Testing.Tests.AutoMocking
+{
+ public class ComponentBeingConfiguredWithInternalCtor
+ {
+ public IReallyCoolService ReallyCoolService;
+ public ICollectionOfServices Services;
+
+ internal
ComponentBeingConfiguredWithInternalCtor(IReallyCoolService
reallyCoolService, ICollectionOfServices services)
+ {
+ ReallyCoolService = reallyCoolService;
+ Services = services;
+ }
+
+ public
ComponentBeingConfiguredWithInternalCtor(IReallyCoolService
reallyCoolService)
+ {
+ ReallyCoolService = reallyCoolService;
+ }
+
+ public void RunDispose()
+ {
+ Services.SomethingToDispose.Dispose();
+ }
+ }
+}
\ No newline at end of file
Index: Rhino.Testing.Tests/AutoMocking/
ComponentBeingConfiguredWithPrivateCtor.cs
===================================================================
--- Rhino.Testing.Tests/AutoMocking/
ComponentBeingConfiguredWithPrivateCtor.cs (revision 0)
+++ Rhino.Testing.Tests/AutoMocking/
ComponentBeingConfiguredWithPrivateCtor.cs (revision 0)
@@ -0,0 +1,23 @@
+namespace Rhino.Testing.Tests.AutoMocking
+{
+ public class ComponentBeingConfiguredWithPrivateCtor
+ {
+ public IReallyCoolService ReallyCoolService;
+ public ICollectionOfServices Services;
+
+ private
ComponentBeingConfiguredWithPrivateCtor(IReallyCoolService
reallyCoolService, ICollectionOfServices services)
+ {
+ ReallyCoolService = reallyCoolService;
+ Services = services;
+ }
+
+ public
ComponentBeingConfiguredWithPrivateCtor(IReallyCoolService
reallyCoolService) : this(reallyCoolService, null)
+ {
+ }
+
+ public void RunDispose()
+ {
+ Services.SomethingToDispose.Dispose();
+ }
+ }
+}
\ No newline at end of file
Index: Rhino.Testing.Tests/AutoMocking/
InternalComponentBeingConfigured.cs
===================================================================
--- Rhino.Testing.Tests/AutoMocking/
InternalComponentBeingConfigured.cs (revision 0)
+++ Rhino.Testing.Tests/AutoMocking/
InternalComponentBeingConfigured.cs (revision 0)
@@ -0,0 +1,19 @@
+namespace Rhino.Testing.Tests.AutoMocking
+{
+ internal class InternalComponentBeingConfigured
+ {
+ public IReallyCoolService ReallyCoolService;
+ public ICollectionOfServices Services;
+
+ internal InternalComponentBeingConfigured(IReallyCoolService
reallyCoolService, ICollectionOfServices services)
+ {
+ ReallyCoolService = reallyCoolService;
+ Services = services;
+ }
+
+ public void RunDispose()
+ {
+ Services.SomethingToDispose.Dispose();
+ }
+ }
+}
\ No newline at end of file
Index: Rhino.Testing.Tests/Rhino.Testing.Tests-vs2008.csproj
===================================================================
--- Rhino.Testing.Tests/Rhino.Testing.Tests-vs2008.csproj (revision
1715)
+++ Rhino.Testing.Tests/Rhino.Testing.Tests-vs2008.csproj (working
copy)
@@ -79,9 +79,12 @@
<Compile Include="AutoMocking\AutoMockingContainerTests.cs" />
<Compile Include="AutoMocking\AutoMockingTests.cs" />
<Compile Include="AutoMocking\ComponentBeingConfigured.cs" />
+ <Compile Include="AutoMocking
\ComponentBeingConfiguredWithInternalCtor.cs" />
+ <Compile Include="AutoMocking
\ComponentBeingConfiguredWithPrivateCtor.cs" />
<Compile Include="AutoMocking\ComponentWithComplexProperty.cs" />
<Compile Include="AutoMocking\DefaultCollectionOfServices.cs" />
<Compile Include="AutoMocking\ICollectionOfServices.cs" />
+ <Compile Include="AutoMocking
\InternalComponentBeingConfigured.cs" />
<Compile Include="AutoMocking\IReallyCoolService.cs" />
<Compile Include="AutoMocking\NeedIKernel.cs" />
<Compile Include="CommentReaderFixture.cs" />
@@ -118,4 +121,4 @@
<Target Name="AfterBuild">
</Target>
-->
-</Project>
+</Project>
\ No newline at end of file
Index: Rhino.Testing/AutoMocking/AutoMockingComponentActivator.cs
===================================================================
--- Rhino.Testing/AutoMocking/AutoMockingComponentActivator.cs
(revision 1715)
+++ Rhino.Testing/AutoMocking/AutoMockingComponentActivator.cs
(working copy)
@@ -1,3 +1,5 @@
+using System;
+using System.Reflection;
using Castle.Core;
using Castle.MicroKernel;
using Castle.MicroKernel.ComponentActivator;
@@ -12,9 +14,14 @@
{
}
- protected override void SetUpProperties(object instance,
CreationContext context)
- {
+ protected override object CreateInstance(CreationContext
context, object[] arguments, System.Type[] signature)
+ {
+ // TODO: Support interceptors + copy "use fast create
instance" logic from DefaultComponentActivator
- }
+ // Support internal and private constructors
+ return Activator.CreateInstance(Model.Implementation,
+
BindingFlags.CreateInstance | BindingFlags.NonPublic |
BindingFlags.Public |
+ BindingFlags.Instance,
null, arguments, null, null);
+ }
}
}
Index: Rhino.Testing/AutoMocking/AutoMockingContainer.cs
===================================================================
--- Rhino.Testing/AutoMocking/AutoMockingContainer.cs (revision 1715)
+++ Rhino.Testing/AutoMocking/AutoMockingContainer.cs (working copy)
@@ -2,10 +2,8 @@
using System.Collections;
using System.Collections.Generic;
using Castle.MicroKernel;
-using Castle.MicroKernel.SubSystems.Naming;
using Castle.Windsor;
using Rhino.Mocks;
-using System.Diagnostics;
namespace Rhino.Testing.AutoMocking
{
@@ -92,6 +90,7 @@
{
Kernel.AddSubSystem(SubSystemConstants.NamingKey,new
AutoMockingNamingSubSystem(this));
Kernel.AddFacility("AutoMockingFacility", new
AutoMockingFacility(this));
+ Kernel.ComponentModelBuilder.AddContributor(new
NonPublicConstructorDependenciesModelInspector());
Kernel.ComponentModelCreated +=
Kernel_ComponentModelCreated;
}
@@ -99,8 +98,9 @@
{
if (model.CustomComponentActivator!=null)
return;
- if (!ResolveProperties)
- model.CustomComponentActivator =
typeof(AutoMockingComponentActivator);
+ model.CustomComponentActivator = ResolveProperties
+ ? typeof
(AutoMockingComponentActivator)
+ : typeof
(NonPropertyResolvingComponentActivator);
}
private void AddComponentIfMissing<T>()
Index: Rhino.Testing/AutoMocking/
NonPropertyResolvingComponentActivator.cs
===================================================================
--- Rhino.Testing/AutoMocking/
NonPropertyResolvingComponentActivator.cs (revision 0)
+++ Rhino.Testing/AutoMocking/
NonPropertyResolvingComponentActivator.cs (revision 0)
@@ -0,0 +1,18 @@
+using Castle.Core;
+using Castle.MicroKernel;
+
+namespace Rhino.Testing.AutoMocking
+{
+ class NonPropertyResolvingComponentActivator :
AutoMockingComponentActivator
+ {
+ public NonPropertyResolvingComponentActivator(ComponentModel
model, IKernel kernel, ComponentInstanceDelegate onCreation,
ComponentInstanceDelegate onDestruction)
+ : base(model, kernel, onCreation, onDestruction)
+ {
+ }
+
+ protected override void SetUpProperties(object instance,
CreationContext context)
+ {
+ // Do nothing - we're not resolving properties
+ }
+ }
+}
\ No newline at end of file
Index: Rhino.Testing/AutoMocking/
NonPublicConstructorDependenciesModelInspector.cs
===================================================================
--- Rhino.Testing/AutoMocking/
NonPublicConstructorDependenciesModelInspector.cs (revision 0)
+++ Rhino.Testing/AutoMocking/
NonPublicConstructorDependenciesModelInspector.cs (revision 0)
@@ -0,0 +1,18 @@
+using System.Reflection;
+using Castle.MicroKernel;
+using Castle.MicroKernel.ModelBuilder.Inspectors;
+
+namespace Rhino.Testing.AutoMocking
+{
+ internal class NonPublicConstructorDependenciesModelInspector :
ConstructorDependenciesModelInspector
+ {
+ public override void ProcessModel(IKernel kernel,
Castle.Core.ComponentModel model)
+ {
+ base.ProcessModel(kernel, model);
+
+ var constructors =
model.Implementation.GetConstructors(BindingFlags.Instance |
BindingFlags.NonPublic);
+ foreach (var constructorInfo in constructors)
+
model.Constructors.Add(CreateConstructorCandidate(model,
constructorInfo));
+ }
+ }
+}
\ No newline at end of file
Property changes on: Rhino.Testing\AutoMocking
\NonPublicConstructorDependenciesModelInspector.cs
___________________________________________________________________
Added: svn:mergeinfo
Index: Rhino.Testing/Rhino.Testing-v2008.csproj
===================================================================
--- Rhino.Testing/Rhino.Testing-v2008.csproj (revision 1715)
+++ Rhino.Testing/Rhino.Testing-v2008.csproj (working copy)
@@ -81,6 +81,8 @@
<Compile Include="AutoMocking\IAutoMockingRepository.cs" />
<Compile Include="AutoMocking\IMockingStrategy.cs" />
<Compile Include="AutoMocking\NonMockedStrategy.cs" />
+ <Compile Include="AutoMocking
\NonPropertyResolvingComponentActivator.cs" />
+ <Compile Include="AutoMocking
\NonPublicConstructorDependenciesModelInspector.cs" />
<Compile Include="AutoMocking\TypeMarker.cs" />
<Compile Include="CommentReader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -115,4 +117,4 @@
<Target Name="AfterBuild">
</Target>
-->
-</Project>
+</Project>
\ No newline at end of file
Cheers
Matt
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Rhino.Mocks" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/RhinoMocks?hl=en
-~----------~----~----~----~------~----~------~--~---