是否可以使用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了。
当前回答
这是一个解决方案。
[Test]
public void TestForOutParameterInMoq()
{
//Arrange
_mockParameterManager= new Mock<IParameterManager>();
Mock<IParameter > mockParameter= new Mock<IParameter >();
//Parameter affectation should be useless but is not. It's really used by Moq
IParameter parameter= mockParameter.Object;
//Mock method used in UpperParameterManager
_mockParameterManager.Setup(x => x.OutMethod(out parameter));
//Act with the real instance
_UpperParameterManager.UpperOutMethod(out parameter);
//Assert that method used on the out parameter of inner out method are really called
mockParameter.Verify(x => x.FunctionCalledInOutMethodAfterInnerOutMethod(),Times.Once());
}
其他回答
对克雷格·塞莱斯特的答案进行了增强,任何人都可以使用它。out参数为IsAny:
public interface IService
{
void DoSomething(out string a);
}
[TestMethod]
public void Test()
{
var service = GetService();
string actualValue;
service.Object.DoSomething(out actualValue);
Assert.AreEqual(expectedValue, actualValue);
}
private IService GetService()
{
var service = new Mock<IService>();
var anyString = It.IsAny<string>();
service.Setup(s => s.DoSomething(out anyString))
.Callback((out string providedString) =>
{
providedString = "SomeValue";
});
return service.Object;
}
如果你的方法也需要返回一些东西,你也可以使用Returns而不是Callback。
似乎不可能开箱即用。看来有人想要解决问题
请看这个论坛帖子 http://code.google.com/p/moq/issues/detail?id=176
这个问题 用最小订货量验证参考参数的值
在VS2022中,你可以简单地做:
foo.Setup(e => e.TryGetValue(out It.Ref<ExampleType>.IsAny))
.Returns((ref ExampleType exampleType) => {
exampleType = new ExampleType();
return true;
})
我相信斯科特的解决方案在某种程度上是有效的,
但是不使用反射来窥探私有api是一个很好的理由。它现在坏了。
我可以使用委托设置参数
delegate void MockOutDelegate(string s, out int value);
public void SomeMethod()
{
....
int value;
myMock.Setup(x => x.TryDoSomething(It.IsAny<string>(), out value))
.Callback(new MockOutDelegate((string s, out int output) => output = userId))
.Returns(true);
}
今天下午,我为此纠结了一个小时,但在任何地方都找不到答案。在我自己玩了一圈之后,我能够想出一个适合我的解决方案。
string firstOutParam = "first out parameter string";
string secondOutParam = 100;
mock.SetupAllProperties();
mock.Setup(m=>m.Method(out firstOutParam, out secondOutParam)).Returns(value);
这里的关键是mock.SetupAllProperties();这将为您清除所有属性。这可能并不适用于每个测试用例场景,但如果您所关心的只是获取YourMethod的返回值,那么这将很好地工作。