Created
October 4, 2013 15:44
-
-
Save djfr/6828042 to your computer and use it in GitHub Desktop.
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
public static class ContractCheckerExtension | |
{ | |
public static string CheckFaultContractMapping<TContract, TEx1>(this MethodInfo method, Action<Mock<WcfService<TContract>>> action) | |
where TContract : class | |
where TEx1 : Exception | |
{ | |
return method.CheckFaultContractMapping<TContract, TEx1, DummyException>(action); | |
} | |
public static string CheckFaultContractMapping<TContract, TEx1, TEx2>(this MethodInfo method, Action<Mock<WcfService<TContract>>> action) | |
where TContract : class | |
where TEx1 : Exception | |
where TEx2 : Exception | |
{ | |
return method.CheckFaultContractMapping<TContract, TEx1, TEx2, DummyException>(action); | |
} | |
public static string CheckFaultContractMapping<TContract, TEx1, TEx2, TEx3>(this MethodInfo method, Action<Mock<WcfService<TContract>>> action) | |
where TContract : class | |
where TEx1 : Exception | |
where TEx2 : Exception | |
where TEx3 : Exception | |
{ | |
return method.CheckFaultContractMapping<TContract, TEx1, TEx2, TEx3, DummyException>(action); | |
} | |
public static string CheckFaultContractMapping<TContract, TEx1, TEx2, TEx3, TEx4>(this MethodInfo method, Action<Mock<WcfService<TContract>>> action) | |
where TContract : class | |
where TEx1 : Exception | |
where TEx2 : Exception | |
where TEx3 : Exception | |
where TEx4 : Exception | |
{ | |
// we're creating a lambda on the fly that will call on the target method | |
// with all parameters set to It.IsAny<[the type of the param]>. | |
var lambda = Expression.Lambda<Action<TContract>>( | |
Expression.Call( | |
Expression.Parameter(typeof (TContract)), | |
method, | |
CreateAnyParameters(method)), | |
Expression.Parameter(typeof (TContract))); | |
// for all the fault contract attributes that are decorating the method | |
foreach (var faultAttr in method.GetCustomAttributes(typeof(FaultContractAttribute), false).Cast<FaultContractAttribute>()) | |
{ | |
// create the specific exception that get's thrown by the fault contract | |
var faultDetail = Activator.CreateInstance(faultAttr.DetailType); | |
var faultExceptionType = typeof(FaultException<>).MakeGenericType(new[] { faultAttr.DetailType }); | |
var exception = (FaultException)Activator.CreateInstance(faultExceptionType, faultDetail); | |
// mock the WCF pipeline objects, channel and client | |
var mockChannel = new Mock<WcfService<TContract>>(); | |
var mockClient = new Mock<TContract>(); | |
// set the mocks | |
mockChannel.Setup(x => x.Channel) | |
.Returns(mockClient.Object); | |
mockClient.Setup(lambda) | |
.Throws(exception); | |
try | |
{ | |
// invoke the client, wrapped in an Action delegate | |
action(mockChannel); | |
} | |
catch (Exception ex) | |
{ | |
// if we get a targeted exception it's because the fault isn't being handled | |
// and we return with the type of the fault contract detail type that was caught | |
if (ex is TEx1 || ex is TEx2 || ex is TEx3 || ex is TEx4) | |
return faultAttr.DetailType.FullName; | |
// else soak all other exceptions because we are expecting them | |
} | |
} | |
return null; | |
} | |
private static IEnumerable<Expression> CreateAnyParameters(MethodInfo method) | |
{ | |
return method.GetParameters() | |
.Select(p => typeof (It).GetMethod("IsAny").MakeGenericMethod(p.ParameterType)) | |
.Select(a => Expression.Call(null, a)); | |
} | |
} | |
[Serializable] | |
public class DummyException : Exception | |
{ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment