EDIT : Moq 4.10 में, आप अब एक प्रतिनिधि को पास कर सकते हैं जिसके पास कॉलबैक फ़ंक्शन के लिए एक आउट या रेफरी पैरामीटर है:
mock
.Setup(x=>x.Method(out d))
.Callback(myDelegate)
.Returns(...);
आपको एक प्रतिनिधि को परिभाषित करना होगा और उसे त्वरित करना होगा:
...
.Callback(new MyDelegate((out decimal v)=>v=12m))
...
4.10 से पहले Moq संस्करण के लिए:
अवनर कश्तन अपने ब्लॉग में एक एक्सटेंशन विधि प्रदान करते हैं जो कॉलबैक से आउट पैरामीटर सेट करने की अनुमति देता है: Moq, कॉलबैक और आउट पैरामीटर: विशेष रूप से मुश्किल एज केस
समाधान सुरुचिपूर्ण और हैकी दोनों है। इसमें सुरुचिपूर्ण यह एक धाराप्रवाह सिंटैक्स प्रदान करता है जो अन्य Moq कॉलबैक के साथ घर पर महसूस करता है। और hacky क्योंकि यह प्रतिबिंब के माध्यम से कुछ आंतरिक Moq API को कॉल करने पर निर्भर करता है।
उपरोक्त लिंक पर प्रदान की गई विस्तार विधि मेरे लिए संकलित नहीं की गई है, इसलिए मैंने नीचे एक संपादित संस्करण प्रदान किया है। आपको प्रत्येक इनपुट पैरामीटर के लिए एक हस्ताक्षर बनाने की आवश्यकता होगी; मैंने 0 और 1 प्रदान किया है, लेकिन इसे आगे बढ़ाना सरल होना चाहिए:
public static class MoqExtensions
{
public delegate void OutAction<TOut>(out TOut outVal);
public delegate void OutAction<in T1,TOut>(T1 arg1, out TOut outVal);
public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, TOut>(this ICallback<TMock, TReturn> mock, OutAction<TOut> action)
where TMock : class
{
return OutCallbackInternal(mock, action);
}
public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, T1, TOut>(this ICallback<TMock, TReturn> mock, OutAction<T1, TOut> action)
where TMock : class
{
return OutCallbackInternal(mock, action);
}
private static IReturnsThrows<TMock, TReturn> OutCallbackInternal<TMock, TReturn>(ICallback<TMock, TReturn> mock, object action)
where TMock : class
{
mock.GetType()
.Assembly.GetType("Moq.MethodCall")
.InvokeMember("SetCallbackWithArguments", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, mock,
new[] { action });
return mock as IReturnsThrows<TMock, TReturn>;
}
}
उपरोक्त विस्तार विधि के साथ, आप बाहर मानकों के साथ एक अंतरफलक का परीक्षण कर सकते हैं जैसे:
public interface IParser
{
bool TryParse(string token, out int value);
}
.. निम्नलिखित Moq सेटअप के साथ:
[TestMethod]
public void ParserTest()
{
Mock<IParser> parserMock = new Mock<IParser>();
int outVal;
parserMock
.Setup(p => p.TryParse("6", out outVal))
.OutCallback((string t, out int v) => v = 6)
.Returns(true);
int actualValue;
bool ret = parserMock.Object.TryParse("6", out actualValue);
Assert.IsTrue(ret);
Assert.AreEqual(6, actualValue);
}
संपादित करें : शून्य-वापसी के तरीकों का समर्थन करने के लिए, आपको बस नए अधिभार तरीकों को जोड़ने की आवश्यकता है:
public static ICallbackResult OutCallback<TOut>(this ICallback mock, OutAction<TOut> action)
{
return OutCallbackInternal(mock, action);
}
public static ICallbackResult OutCallback<T1, TOut>(this ICallback mock, OutAction<T1, TOut> action)
{
return OutCallbackInternal(mock, action);
}
private static ICallbackResult OutCallbackInternal(ICallback mock, object action)
{
mock.GetType().Assembly.GetType("Moq.MethodCall")
.InvokeMember("SetCallbackWithArguments", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, mock, new[] { action });
return (ICallbackResult)mock;
}
यह परीक्षण इंटरफेस जैसे:
public interface IValidationRule
{
void Validate(string input, out string message);
}
[TestMethod]
public void ValidatorTest()
{
Mock<IValidationRule> validatorMock = new Mock<IValidationRule>();
string outMessage;
validatorMock
.Setup(v => v.Validate("input", out outMessage))
.OutCallback((string i, out string m) => m = "success");
string actualMessage;
validatorMock.Object.Validate("input", out actualMessage);
Assert.AreEqual("success", actualMessage);
}
It.IsAny<T>()
-समान मिलानकर्ता (ref It.Ref<T>.IsAny
) से लेकर सेट अप करने के लिए.Callback()
और.Returns()
कस्टम हस्ताक्षर प्रकार के माध्यम से समर्थन करने के लिए विधि हस्ताक्षर हैं। संरक्षित तरीके समान रूप से समर्थित हैं। नीचे मेरा जवाब उदा देखें ।