Moq回调不修改输入参数

本文关键字:输入 参数 修改 回调 Moq | 更新日期: 2023-09-27 18:07:39

问题:

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

更多细节:

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

我接口:

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);

Moq回调不修改输入参数

将本地变量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将包含添加的值。