是否可以使用Moq(3.0+)分配一个out/ref参数?
我已经看过使用Callback(),但Action<>不支持ref参数,因为它是基于泛型的。我还希望在ref参数的输入上放置一个约束(It.Is),尽管我可以在回调中这样做。
我知道Rhino Mocks支持这个功能,但是我正在做的项目已经在使用Moq了。
是否可以使用Moq(3.0+)分配一个out/ref参数?
我已经看过使用Callback(),但Action<>不支持ref参数,因为它是基于泛型的。我还希望在ref参数的输入上放置一个约束(It.Is),尽管我可以在回调中这样做。
我知道Rhino Mocks支持这个功能,但是我正在做的项目已经在使用Moq了。
当前回答
在我简单地创建一个新的“Fake”类的实例来实现您试图Mock的任何接口之前,我在这里的许多建议中苦苦挣扎。然后,您可以简单地使用方法本身设置out参数的值。
其他回答
对于“out”,下面的方法似乎对我有用。
public interface IService
{
void DoSomething(out string a);
}
[TestMethod]
public void Test()
{
var service = new Mock<IService>();
var expectedValue = "value";
service.Setup(s => s.DoSomething(out expectedValue));
string actualValue;
service.Object.DoSomething(out actualValue);
Assert.AreEqual(expectedValue, actualValue);
}
我猜当你调用Setup并记住它时,Moq会查看“expectedValue”的值。
作为裁判,我也在寻找答案。
我发现下面的快速入门指南很有用: https://github.com/Moq/moq4/wiki/Quickstart
在Billy Jakes awnser的基础上,我用一个out参数做了一个完全动态的模拟方法。我把这个贴在这里给那些觉得有用的人。
// Define a delegate with the params of the method that returns void.
delegate void methodDelegate(int x, out string output);
// Define a variable to store the return value.
bool returnValue;
// Mock the method:
// Do all logic in .Callback and store the return value.
// Then return the return value in the .Returns
mockHighlighter.Setup(h => h.SomeMethod(It.IsAny<int>(), out It.Ref<int>.IsAny))
.Callback(new methodDelegate((int x, out int output) =>
{
// do some logic to set the output and return value.
output = ...
returnValue = ...
}))
.Returns(() => returnValue);
为了返回一个值和设置ref参数,这里有一段代码:
public static class MoqExtensions
{
public static IReturnsResult<TMock> DelegateReturns<TMock, TReturn, T>(this IReturnsThrows<TMock, TReturn> mock, T func) where T : class
where TMock : class
{
mock.GetType().Assembly.GetType("Moq.MethodCallReturn`2").MakeGenericType(typeof(TMock), typeof(TReturn))
.InvokeMember("SetReturnDelegate", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, mock,
new[] { func });
return (IReturnsResult<TMock>)mock;
}
}
然后声明自己的与要模拟方法的签名匹配的委托,并提供自己的方法实现。
public delegate int MyMethodDelegate(int x, ref int y);
[TestMethod]
public void TestSomething()
{
//Arrange
var mock = new Mock<ISomeInterface>();
var y = 0;
mock.Setup(m => m.MyMethod(It.IsAny<int>(), ref y))
.DelegateReturns((MyMethodDelegate)((int x, ref int y)=>
{
y = 1;
return 2;
}));
}
这是来自Moq网站的文档:
// out arguments
var outString = "ack";
// TryParse will return true, and the out argument will return "ack", lazy evaluated
mock.Setup(foo => foo.TryParse("ping", out outString)).Returns(true);
// ref arguments
var instance = new Bar();
// Only matches if the ref argument to the invocation is the same instance
mock.Setup(foo => foo.Submit(ref instance)).Returns(true);
在我简单地创建一个新的“Fake”类的实例来实现您试图Mock的任何接口之前,我在这里的许多建议中苦苦挣扎。然后,您可以简单地使用方法本身设置out参数的值。