Reputation: 135
I'm trying to unit test a factory class that uses reflection to construct an unknown object that derives from a known base class.
However, I'm getting an exception when the factory tries to invoke the the constructor derived from my fake unit's type. It's a null reference exception.
I'm using FakeItEasy. Here's What I have going on here:
[TestFixture]
public class DisplayUnitFactoryTests
{
private readonly IDisplayUnitPluginContainer _mgr = A.Fake<IDisplayUnitPluginContainer>();
private readonly DisplayUnitPlugin _plgin = A.Fake<DisplayUnitPlugin> ();
private DisplayUnit _unit;
private Guid _guid;
[TestFixtureSetUp]
public void init()
{
_unit = A.Fake<DisplayUnit> (p=> p.WithArgumentsForConstructor(new object[]{new Dictionary<string,string>()}));
_guid = Guid.NewGuid ();
A.CallTo (() => _mgr.Resolve (VALID_STRING)).Returns (_plgin);
A.CallTo (() => _mgr.Resolve (INVALID_STRING)).Returns (null);
A.CallTo (() => _plgin.DisplayUnitType).Returns (_unit.GetType ());
}
That bottom line is my issue. DisplayUnit is an abstract class. It's implementation shouldn't matter in this situation except for its constructor. However, DisplayUnit has a constructor that requires a Dictionary as a parameter.
If I use a REAL type (not faked), the code works fine. (e.g. A.CallTo(() => _plgin.DisplayUnitType).Returns(typeof(TextUnit));
However, That real type requires a dependency outside my core code. I want different types of DisplayUnits to be added at runtime as plugins. Thus, I want to unit test my DisplayUnitFactory using a fake Display Unit. In this test, I shouldn't need to depend on an outside assembly in order to make this work.
Here's my test.
[Test]
public void InstantiateNew_ValidPluginID_EmptyDict_ReturnsCorrectDisplayUnit()
{
var factory = new DisplayUnitFactory (_mgr);
var du = factory.InstantiateNew (VALID_STRING, new Dictionary<string, string> ());
Assert.That (du, Is.Not.Null);
}
Here's my factory code:
public DisplayUnit InstantiateNew (string pluginId, Dictionary<string, string> attributes)
{
return getDisplayUnit (pluginId, attributes);
}
private DisplayUnit getDisplayUnit(string pluginId, Dictionary<string,string> attributes)
{
//Get the constructor that accepts only a dictionary<string,string>.
var ctor = getCtor (pluginId, new Type[]{typeof(Dictionary<string,string>)});
//Invoke it with the attributes dictionary.
var unit = ctor.Invoke (new object[]{ attributes }) as DisplayUnit;
return unit;
}
private ConstructorInfo getCtor(string pluginId, Type[] paramTypes)
{
var plugin = _container.Resolve (pluginId);
if (plugin == null)
throw new NotRegisteredPluginException ("Plugin not registered: " + pluginId);
var type = plugin.DisplayUnitType;
return type.GetConstructor (paramTypes);
}
Essentially, I need to fake the ConstructorInfo that will come out using Reflection, and ultimately fake the return from ConstructorInfo.Invoke(). But I'm getting a null reference exception in getDisplayUnit()
when the constructor is invoked, because the ctor
is coming back null.
Help!
Upvotes: 1
Views: 750
Reputation: 135
So Thanks to Blair, I believe I've found the solution: It's not to use a Fake at all.
The faked type will have only a single public constructor, with arguments
Castle.DynamicProxy.IInterceptor[], Dictionary<System.String,System.String>
.
Thus the whole process was breaking down when Reflection tried to get a constructor.
The solution was to create a DummyDisplayUnit
that derived from DisplayUnit
and use that instead. This worked just fine, without needing a fake.
I guess sometimes I try to abstract to the point where I miss the obvious solution...
Upvotes: 3