Moq回调不修改输入参数

时间:2014-06-09 18:51:43

标签: c# unit-testing ado.net moq

问题:

下面的代码不允许我修改我传递给Moq模拟的方法的参数。

其他详细信息:

我正在尝试模拟一个提供名为ExecuteStoredProcedureWithParameters的方法的通用数据访问对象。该方法接受两个参数:存储过程名称和SqlParameter个对象的集合。我有通过输出参数返回值的存储过程,所以我试图模拟数据访问方法并修改输出参数的值(它是传入的SqlParameter集合的成员)。根据我的研究,我下面的代码似乎应该可以工作(我只是试图通过将它们设置为空/ null来修改输入参数以进行测试)。我在模拟设置中指定的返回值被返回并存储在retval中,但是testProceduretestParameters的值在执行模拟方法后保持不变。我做错了什么,如何修改传递给我的mock方法的对象?

我的界面:

public interface IGenericDAO
{
    int ExecuteStoredProcedureWithParameters(string procedureName, Collection<SqlParameter> parameters);
}

测试方法:

// Create a mock generic DAO
var mock = new Mock<IGenericDAO>();
mock.Setup(x => x.ExecuteStoredProcedureWithParameters("TestProcedure", It.IsAny<Collection<SqlParameter>>()))
    .Returns(111)
    .Callback<string, Collection<SqlParameter>>((proc, prms) => { proc = string.Empty; prms = null; });

// Execute the mocked method with dummy parameters
var testProcedure = "TestProcedure";
var testParameters = new Collection<SqlParameter>();
var retval = mock.Object.ExecuteStoredProcedureWithParameters(testProcedure, testParameters);

1 个答案:

答案 0 :(得分:2)

您正在将局部变量prms设置为null。由于标准的 按值传递 语义,这对实际的testParameters变量没有影响。 Collection通过值传递给函数,因此像任何其他变量一样被浅层复制。你在做什么类似于这个简单的例子:

void A()
{
    int x = 10;
    B(x);
    Console.WriteLine(x); // 'x' is still 10
}

void B(int x) // input argument copied into local 'x'
{
    x = 20;   // local 'x' modified
}             // local 'x' discarded

这将打印出10,因为只修改本地副本x,然后在函数末尾抛弃。

在您的实际示例中,如果执行类似prms.Add(new SqlParameter(...))的操作,则在通话结束时,testParameters将包含附加值。