Created
August 23, 2012 01:29
-
-
Save programatt/3431096 to your computer and use it in GitHub Desktop.
Any order mocked construction parameters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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