Matt Ellis
unread,Nov 4, 2008, 12:00:55 PM11/4/08Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to Rhino.Mocks
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