使用 Moq,如何模拟使用局部变量的方法

rob*_*b23 4 c# unit-testing moq

Moq 的新手,这是一个非常简单的示例。我想模拟对我的方法“string getCode(int someID)”中使用的“int steamTest(int a, int b)”方法的调用。在 getCode 中声明并设置了用于冒烟测试的变量。问题是当我模拟对smoothTest 的方法调用时,我总是在getCode 中得到“0”的结果,但我想看到我的预定义结果“20”。我发现的唯一解决方法是重载方法并传入所有变量。但是,我不想这样做,因为我要测试的许多方法都声明并使用局部变量。使用 Moq 测试此方法的最佳方法是什么?谢谢

// Example A
public string getCode(int someID)
{
    int x = 5;
    int y = 5;
    int z = _dataAccess.smokeTest(x, y);

    return _dataAccess.getCode(someID);
}

// NOTE: Doesn't work as wanted
[Test]
public void test_getCode_TestB()
{
    var x = It.IsAny<int>();
    var y = It.IsAny<int>();

    // NOTE: "20" is not returned, 0 is returned instead because local variables are used
    _mockDataAccess.Setup(m => m.smokeTest(x, y)).Returns(20);
    _mockDataAccess.Setup(m => m.getCode(234)).Returns("def345");

    var result = _businessLogic.getCode(234);

    Assert.IsTrue(result == "def345");
}

// Example B

// NOTE: Workaround - pass in variables
public string getCode(int someID, int a, int b)
{
    var c = _dataAccess.smokeTest(a, b);
    return _dataAccess.getCode(someID);
}       

[Test]
public void test_getCode_TestC()
{
    var x = It.IsAny<int>();
    var y = It.IsAny<int>();

    // NOTE: "20" is returned as wanted
    _mockDataAccess.Setup(m => m.smokeTest(x, y)).Returns(20);
    _mockDataAccess.Setup(m => m.getCode(234)).Returns("def345");

    var result = _businessLogic.getCode(234, x, y);
    Assert.IsTrue(result == "def345");
}
Run Code Online (Sandbox Code Playgroud)

Yuv*_*hap 6

仅当您It.IsAny<int>()直接进入最小起订量设置时,它才会起作用:

_mockDataAccess.Setup(m => m.smokeTest(It.IsAny<int>(), It.IsAny<int>())).Returns(20);
Run Code Online (Sandbox Code Playgroud)

我正在浏览 moq 源代码以发现这样做:

int x = It.IsAny<int>();
int y = It.IsAny<int>();
_mockDataAccess.Setup(m => m.smokeTest(x, y)).Returns(20);
Run Code Online (Sandbox Code Playgroud)

将 x 和 y 指定为 int 的默认值,即 0,因此您的设置等效于:

_mockDataAccess.Setup(m => m.smokeTest(0, 0)).Returns(20); 
Run Code Online (Sandbox Code Playgroud)

如果参数为 0 和 0,此设置告诉 moq 返回 20,否则将返回 int 的默认值,该值再次为 0。这不是您打算创建的行为,因此在将It.IsAny<int>()x 和 y 传递到 moq 设置之前,不应将它们分配给它们。

正如@Rob 注释所指出的,It.IsAny<T>是一种可以传递到 moq 设置中的存根,设置方法将知道如何使用Expression Trees处理它,但此方法实际返回的值始终是 T 的默认值。这是为什么我们必须始终直接在最小起订量设置中使用此方法。