After taking a look at the source code for the AutoMocker<TTargetClass>
class, I noticed the following:
- AutoMocker uses a StructureMap container under the covers
- usually all dependencies are directly resolved using the container
- dependencies that are of type
IEnumerable<T>
are treated differently (see below)
Here's a piece of code from the AutoMocker<TTargetClass>
class that shows how constructor dependencies are resolved (I removed some lines for brevity):
private object[] getConstructorArgs()
{
ConstructorInfo ctor = Constructor.GetGreediestConstructor(typeof (TTargetClass));
var list = new List<object>();
foreach (ParameterInfo parameterInfo in ctor.GetParameters())
{
Type dependencyType = parameterInfo.ParameterType;
if (dependencyType.IsArray)
{
[...]
}
else if (dependencyType.Closes(typeof (IEnumerable<>)))
{
Type @interface = dependencyType.FindFirstInterfaceThatCloses(typeof (IEnumerable<>));
Type elementType = @interface.GetGenericArguments().First();
// Here's the interesting code:
var builder = typeof (EnumerableBuilder<>).CloseAndBuildAs<IEnumerableBuilder>(_container,
elementType);
list.Add(builder.ToEnumerable());
}
else
{
object dependency = _container.GetInstance(dependencyType);
list.Add(dependency);
}
}
return list.ToArray();
}
The code shows that dependencies are usually resolved using _container.GetInstance
, but there are two exceptions: ararys and IEnumerable<>
s
For IEnumerable<T>
, it turns out that _container.GetAllInstances(typeof(T))
is used. This meas that in your case you should inject several IItem
instances, not an IEnumerable<IItem>
. The code responsible for this is the EnumerableBuilder<T>
class, whih can be found in the same file (at the end).
OK, enough talk. I'm not sure if my explanation is clear enough, so below is code for two tests that pass. Hopefully that will clarify everything:
[Test]
public void Test_OneItem()
{
var autoMocker = new RhinoAutoMocker<TestClass1>();
autoMocker.Inject(MockRepository.GenerateMock<IItem>());
Assert.AreEqual(1, autoMocker.ClassUnderTest.Items.Count());
}
[Test]
public void Test_TwoItems()
{
var autoMocker = new RhinoAutoMocker<TestClass1>();
autoMocker.Inject(MockRepository.GenerateMock<IItem>());
autoMocker.Inject(MockRepository.GenerateMock<IItem>());
Assert.AreEqual(2, autoMocker.ClassUnderTest.Items.Count());
}