Builder pattern
I was writing unit tests when I stumbled on a problem. I had a class TransitionInfo which I couldn't instantiate.
The constructor was made internal. Also, all the properties were getters, so I couldn't set any of them. So, there was only one thing todo: Reflection !!
The TransitionInfo object was used in more than 1 unit tests. In fact, it was used in alot of them. So I had to copy all this ugly reflection code in each unit test.
I couldn't do this of course. I hate copy pasting.
So I talked to our Architect on the team and he put me on the right track.
This is how I implemented the solution:
First I had to create a sort of builder class which was goin to encapsulate all of the reflection code. The purpose of the builder class was to give me a constructed TransitionInfo object.
This is the code:
internal class TransitionInfoBuilder
{
// Create our return object
private TransitionInfo expectedTransitionInfo;
public TransitionInfoBuilder()
{
Type type = typeof(TransitionInfo);
Type[] constructorParameterTypes = new Type[]
{ typeof(TransitionTrigger), typeof(string), typeof(int), typeof(string), typeof(string),
typeof(string) };
// Get the internal constructor
ConstructorInfo cInfo = type.GetConstructor(BindingFlags.Instance
BindingFlags.NonPublic, null,
CallingConventions.HasThis,
constructorParameterTypes,
null);
// Call invoke and instantiate the return object
expectedTransitionInfo = (TransitionInfo) cInfo.Invoke(new object[]
{ TransitionTrigger.After, "", 0, "", "", "" }); }
// Let's fill in some private field:
public TransitionInfoBuilder WithItemId(int itemId)
{
// Set the private field
SetTransitionField(itemId, "m_ItemId");
// Return a builder object
return this;
}
// Now we have to expose the transitionInfo object
public TransitionInfo Stub
{
get
{
return this.expectedTransitionInfo;
}
}
// Use reflection to set the private field
private void SetTransitionField(object fieldValue, string fieldName)
{
Type myType = typeof(TransitionInfo);
FieldInfo myFieldInfo = myType.GetField(fieldName, BindingFlags.NonPublic
BindingFlags.Instance);
myFieldInfo.SetValue(expectedTransitionInfo, fieldValue);
}
Now we can call the builder class and retrieve our stubbed TransitionInfo object
TransitionInfo transitionInfo = new TransitionInfoBuilder()
.WithItemId(1)
.Stub;
Greetz,
Glenn
comments are always welcome
The constructor was made internal. Also, all the properties were getters, so I couldn't set any of them. So, there was only one thing todo: Reflection !!
The TransitionInfo object was used in more than 1 unit tests. In fact, it was used in alot of them. So I had to copy all this ugly reflection code in each unit test.
I couldn't do this of course. I hate copy pasting.
So I talked to our Architect on the team and he put me on the right track.
This is how I implemented the solution:
First I had to create a sort of builder class which was goin to encapsulate all of the reflection code. The purpose of the builder class was to give me a constructed TransitionInfo object.
This is the code:
internal class TransitionInfoBuilder
{
// Create our return object
private TransitionInfo expectedTransitionInfo;
public TransitionInfoBuilder()
{
Type type = typeof(TransitionInfo);
Type[] constructorParameterTypes = new Type[]
{ typeof(TransitionTrigger), typeof(string), typeof(int), typeof(string), typeof(string),
typeof(string) };
// Get the internal constructor
ConstructorInfo cInfo = type.GetConstructor(BindingFlags.Instance
BindingFlags.NonPublic, null,
CallingConventions.HasThis,
constructorParameterTypes,
null);
// Call invoke and instantiate the return object
expectedTransitionInfo = (TransitionInfo) cInfo.Invoke(new object[]
{ TransitionTrigger.After, "", 0, "", "", "" }); }
// Let's fill in some private field:
public TransitionInfoBuilder WithItemId(int itemId)
{
// Set the private field
SetTransitionField(itemId, "m_ItemId");
// Return a builder object
return this;
}
// Now we have to expose the transitionInfo object
public TransitionInfo Stub
{
get
{
return this.expectedTransitionInfo;
}
}
// Use reflection to set the private field
private void SetTransitionField(object fieldValue, string fieldName)
{
Type myType = typeof(TransitionInfo);
FieldInfo myFieldInfo = myType.GetField(fieldName, BindingFlags.NonPublic
BindingFlags.Instance);
myFieldInfo.SetValue(expectedTransitionInfo, fieldValue);
}
Now we can call the builder class and retrieve our stubbed TransitionInfo object
TransitionInfo transitionInfo = new TransitionInfoBuilder()
.WithItemId(1)
.Stub;
Greetz,
Glenn
comments are always welcome