如何使用多个Ref参数模拟一个方法

时间:2011-12-01 08:41:30

标签: unit-testing mocking nunit moq pass-by-reference

我有这个方法调用

SecurityController.GetUserPermissions( _
     HttpContext.Current.User.Identity.Name.ToString, GroupAdmin, GroupTrans)

其中GroupAdmin和GroupTrans是字符串数组,是ByRef参数。

所以基本上它的作用是,给定用户名填写管理员权限数组和允许的交易数组。

这是我无法改变的遗留代码。

这是我测试的一部分:

var moqSecurityController = new Mock<ISecurityController>();
var refParam = new string[1] {"test"};
moqSecurityController
   .Setup(x => x.GetUserPermissions("Bob", ref refParam, ref refParam))
   .Callback((string userName, string[] groupAdmin, string[] groupTrans) =>
                                                 {
                                                    groupAdmin[0] = "Test a";
                                                    groupTrans[0] = "Test b";
                                                 });

最后我希望在GroupAdmin和GroupTrans中都有“测试”,但我得到了 错误:

Invalid callback. Setup on method with parameters (String,String[]&,String[]&)
cannot invoke callback with parameters (String,String[],String[])

我错过了什么?谁能帮我嘲笑这个?

由于

2 个答案:

答案 0 :(得分:4)

经过一些“艰苦”的工作后找到了解决方案

var moqSecurityController = new Mock<ISecurityController>();
moqSecurityController
    .Setup(x => x.GetUserPermissions(
           It.IsAny<string>(), ref groupAdmin, ref groupTrans))
    .Returns((string s, string[] a, string[] b) =>
           {
               a[0] = "TestAdmin";
               b[0] = "TestTrans";
               return 0;
           });

问题是错误使用Callback而不是Return

答案 1 :(得分:0)

我知道你的解决方案有效,并且理解这是一篇旧帖子,但这是未来人们的另一个更简单的实现版本:)

存储库方法:

    public T Get<T>(params KeyValuePair<string, object>[] parameters) where T : class
    {
        // do whatever you need to do and return an object of type T;
    }

业务类的UnitTest方法:

    [TestCategory("UnitTest")]
    [TestMethod]
    public void UnitTest_Business_BusinessClassName_GetMethodName()
    {
        var mockRepositoryName = new Mock<IRepositoryName>(MockBehavior.Strict);
        var businessClassName = new BusinessClassName(mockRepositoryName.Object);
        var inputValue = GetInput();
        var expectedResponse = new ResultModel { Id = 1 };

        #region Moq

        var paramsValue = new KeyValuePair<string, object>("Id", inputValue);

        mockRepositoryName
            .Setup(
                p => p.Get<ResultModel>
                    (
                        It.Is<KeyValuePair<string, object>>(i => CheckInputs(i, paramsValue))
                    )
                )
            .Returns(expectedResponse)
            ;

        #endregion Moq

        ResultModel actual = businessClassName.Get(inputValue);

        #region assertion

        Assert.IsNotNull(actual, "actual");
        Assert.AreEqual(inputValue, actual.Id, "Id");

        #endregion
    }

    private static int GetInput()
    {
        return 1;
    }

    private static bool CheckInputs(KeyValuePair<string, object> source, KeyValuePair<string, object> target)
    {
            if (string.IsNullOrWhiteSpace(source.Value?.ToString()) ||
                string.IsNullOrWhiteSpace(target.Value?.ToString()) ||
                int.Parse(source.Value.ToString()) != int.Parse(target.Value.ToString()))
            {
                return false;
            }
        return true;
    }

你们都已经准备好了。