如何根据输入获取MOQ设置以更改输出参数?

时间:2015-10-09 14:38:04

标签: c# moq out

MOQ支持输出参数的设置 - 没问题。我希望能够通过Returns()或Callback()根据调用中传递的内容设置参数。我的用例涉及使用out参数模拟一个方法。

以下是我用于实验的内容,到目前为止每次都有负面结果:

public interface ITestClass
{
    string method(string inString, out string outString);
}

public class TestClass : ITestClass
{
    public string method(string inString, out string outString)
    {
        outString = inString + " was passed in";
        return (inString + " was returned");
    }
}

[TestFixture]
public class OutTest
{
    [Test]
    public void Test()
    {
        //Arrange
        Mock<ITestClass> mock = new Mock<ITestClass>(MockBehavior.Strict);
        string stringParm = "value that will be assigned to out parameter";
        mock.Setup(t => t.method(It.IsAny<string>(), out stringParm))
            .Returns((string i, string o) =>
            {
                return i + " was returned"; // o = stringParm already
            })
            .Callback((string s, string oo) =>
            {
                stringParm = s + " was passed in"; // oo = stringParm already
            });
        TestClass real = new TestClass();
        string testString = DateTime.Now.ToLongTimeString();

        //Act
        string realOut;
        string mockOut;
        string realResult = real.method(testString, out realOut);
        string mockResult = mock.Object.method(testString, out mockOut);

        //Assert
        realResult.Should().Be(mockResult); // passes
        realOut.Should().Be(mockOut); // fails - mockout = original stringParm
    }
}

2 个答案:

答案 0 :(得分:0)

我知道这不理想,但为什么不传递预期的mockOut代替"value that will be assigned to out parameter"

string stringParm = "foo was passed in"

答案 1 :(得分:0)

我最近不得不更新我使用的解决方案,以便在没有参数的情况下对设置执行回调。

namespace SupRep.TestUtilities
{
    using System.Reflection;
    using Moq.Language;
    using Moq.Language.Flow;

    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 delegate void OutAction<in T1,in T2,TOut>(T1 arg1, T2 arg2, 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);
        }

        public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, T1, T2, TOut>(this ICallback<TMock, TReturn> mock, OutAction<T1, T2, 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
        {
            var methodCall = mock.GetType().GetProperty("Setup").GetValue(mock);
            mock.GetType().Assembly.GetType("Moq.MethodCall")
                .InvokeMember("SetCallbackResponse", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, methodCall,
                    new[] { action });
            return mock as IReturnsThrows<TMock, TReturn>;
        }
    }}