Hallo zusammen,
ich bin gerade dabei das Moq Framework etwas näher anzuschauen. Dabei fällt mir auf das ich momentan Probleme habe Methoden zu mocken, die ref und out Parameter haben. Mein Lösungsansatz geht dabei in die Untiefen von Reflection. Kennt jemand eine andere Lösung um ref und out Parameter in Methoden zu mocken? Zur Zeit verwende ich Moq v4.5.28.0.
Bisher habe ich folgende Lösung basierend auf Assigning out/ref parameters in Moq (StackOverflow):
mein Interface sehe so aus:
im Unittest würde ich dann folgendes machen:
Gibt es eine Möglichkeit Delegates mit ref/out Parametern ohne Reflection zu verwenden?
Viele Grüße
Rossibaer
ich bin gerade dabei das Moq Framework etwas näher anzuschauen. Dabei fällt mir auf das ich momentan Probleme habe Methoden zu mocken, die ref und out Parameter haben. Mein Lösungsansatz geht dabei in die Untiefen von Reflection. Kennt jemand eine andere Lösung um ref und out Parameter in Methoden zu mocken? Zur Zeit verwende ich Moq v4.5.28.0.
Bisher habe ich folgende Lösung basierend auf Assigning out/ref parameters in Moq (StackOverflow):
Code:
public static class MockExtensions
{
public static IReturnsThrows<TMock, TReturn> Returns<TMock, TReturn>(this ICallback<TMock, TReturn> mock, Delegate action)
where TMock : class
{
return SetReturns(mock, action);
}
public static ICallbackResult Callback(this ICallback mock, Delegate action)
{
return SetCallback(mock, action);
}
private static IReturnsThrows<TMock, TReturn> SetReturns<TMock, TReturn>(ICallback<TMock, TReturn> mock, object action)
where TMock : class
{
var genericMethodCallReturn = mock
.GetType()
.Assembly
.GetTypes()
.First(t => t.FullName.StartsWith("Moq.MethodCallReturn", StringComparison.InvariantCultureIgnoreCase) && t.IsGenericType);
var constructedMethodCallReturn = genericMethodCallReturn.MakeGenericType(typeof(TMock), typeof(TReturn));
constructedMethodCallReturn.InvokeMember("SetReturnDelegate", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, mock, new[] { action });
return (IReturnsThrows<TMock, TReturn>) mock;
}
private static ICallbackResult SetCallback(ICallback mock, object action)
{
var methodCall = mock
.GetType()
.Assembly.GetType("Moq.MethodCall");
methodCall.InvokeMember("SetCallbackWithArguments", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, mock, new[] { action });
return (ICallbackResult)mock;
}
}
mein Interface sehe so aus:
Code:
public interface IMyInterface
{
bool Check(out Type targetType, ref string propertyName);
void Apply(out Type targetType, ref string propertyName);
}
im Unittest würde ich dann folgendes machen:
Code:
public delegate bool CheckDelegate(out Type targetType, ref string propertyName);
public delegate void ApplyDelegate(out Type targetType, ref string propertyName);
[TestMethod]
public void MyTest1()
{
var targetType1 = It.IsAny<Type>();
var propertyName1 = It.IsAny<string>();
var targetType2 = It.IsAny<Type>();
var propertyName2 = It.IsAny<string>();
var mock = new Mock<IMyInterface>();
mock
.Setup(obj => obj.Check(out targetType1, ref propertyName1))
.Returns((CheckDelegate)((out Type t, ref string p) =>
{
t = typeof(Guid);
p = Guid.NewGuid().ToString();
return true;
}));
mock
.Setup(obj => obj.Apply(out targetType2, ref propertyName2))
.Callback((ApplyDelegate)((out Type t, ref string p) =>
{
t = typeof(string);
p = Guid.NewGuid().ToString();
}));
var sut = mock.Object;
if (sut.Check(out targetType1, ref propertyName1))
sut.Apply(out targetType2, ref propertyName2);
Assert.AreNotEqual(typeof(object), targetType1);
Assert.AreNotEqual(Guid.Empty.ToString(), propertyName1);
Assert.AreNotEqual(typeof(object), targetType2);
Assert.AreNotEqual(Guid.Empty.ToString(), propertyName2);
}
Gibt es eine Möglichkeit Delegates mit ref/out Parametern ohne Reflection zu verwenden?
Viele Grüße
Rossibaer