Skip to content

Instantly share code, notes, and snippets.

@programatt
Created August 23, 2012 01:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save programatt/3431096 to your computer and use it in GitHub Desktop.
Save programatt/3431096 to your computer and use it in GitHub Desktop.
Any order mocked construction parameters
using System;
using System.Linq;
using Moq;
using Xunit;
namespace Tests.UnitTests.Services
{
public class TestableTypeFactory
{
public static T GetType<T>(params object[] constructorParameters)
{
var ctors = typeof (T).GetConstructors();
var ctor = ctors
//.Where(c => c.GetParameters().Length > 0)
//.OrderBy(c => c.GetParameters().Length)
.FirstOrDefault();
if (ctor == null) throw new ArgumentException("Cannot instantiate type because it doesnt have a non-default constructor");
//Get parameter list for constructor
var requiredParamList = ctor.GetParameters();
//create type needed to hold the values of the parameters
var invokeParameters = new object[requiredParamList.Length];
//null means mock them all
if (constructorParameters == null)
{
var i = 0;
foreach (var parameter in requiredParamList)
{
invokeParameters[i] = Generate(parameter.ParameterType).Object;
i++;
}
}
else
{
//get types of parameters
var constructorParametersTypes = constructorParameters.ToList().ConvertAll(c => c.GetType());
//loop through the parameter list for the constructor
var i = 0;
foreach (var parameter in requiredParamList)
{
var param = constructorParameters.ToList().SingleOrDefault(p=>p.GetType() == parameter.ParameterType);
invokeParameters[i] = param ?? Generate(parameter.ParameterType).Object;
i++;
}
}
//invoke the constructor and return the result
return (T)ctor.Invoke(invokeParameters);
}
private static Mock Generate(Type type)
{
if (type == null)
throw new ArgumentException("type");
var genericCtor = typeof(Mock<>).MakeGenericType(type).GetConstructor(new Type[0]);
var ret = (Mock)genericCtor.Invoke(new object[0]);
// TODO: add some commonly wanted features. Maybe auto-property setup
return ret;
}
}
public interface A{}
public interface B{}
public interface C{}
public class Foo
{
private A _a;
private B _b;
private C _c;
public Foo(A a,B b,C c)
{
_a = a;
_b = b;
_c = c;
}
}
public class Tests
{
[Fact]
public void TestEmptyParameterListPassed()
{
var foo = TestableTypeFactory.GetType<Foo>(null);
}
[Fact]
public void TestFullParamListPassed()
{
var a = new Mock<A>();
var b = new Mock<B>();
var c = new Mock<C>();
var foo = TestableTypeFactory.GetType<Foo>(new object[] { a, b, c });
}
[Fact]
public void TestPartialParamsListPassed()
{
var a = new Mock<A>();
var b = new Mock<B>();
var foo = TestableTypeFactory.GetType<Foo>(new object[] {a, b});
}
[Fact]
public void TestOutOfOrderFullParamsPassed()
{
var a = new Mock<A>();
var b = new Mock<B>();
var c = new Mock<C>();
var foo = TestableTypeFactory.GetType<Foo>(new object[] {c, b, a});
}
[Fact]
public void TestOutOfOrderPartialParamsPassed()
{
var c = new Mock<C>();
var a = new Mock<A>();
var foo = TestableTypeFactory.GetType<Foo>(new object[] {c, a});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment