使用 Moq,如何模拟使用局部变量的方法
Using Moq, How do you Mock a method that uses local variables
Moq 新手,这是一个非常简单的示例。我想模拟对我的方法 "string getCode(int someID)" 中使用的 "int smokeTest(int a, int b)" 方法的调用。 smokeTest 的变量在 getCode 中声明和设置。问题是当我模拟对 smokeTest 的方法调用时,我总是在 getCode 中得到“0”的结果,但我想看到我的预定义结果“20”。我发现的唯一解决方法是重载该方法并传入所有变量。但是,我不想这样做,因为我要测试的许多方法都声明并使用局部变量。使用最小起订量测试此方法的最佳方法是什么?谢谢
// 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");
}
仅当您将 It.IsAny<int>()
直接传递到最小起订量设置时才会起作用:
_mockDataAccess.Setup(m => m.smokeTest(It.IsAny<int>(), It.IsAny<int>())).Returns(20);
我在浏览最小起订量源代码时发现这样做:
int x = It.IsAny<int>();
int y = It.IsAny<int>();
_mockDataAccess.Setup(m => m.smokeTest(x, y)).Returns(20);
会将 x 和 y 指定为 int 的默认值,即 0,因此您的设置等同于:
_mockDataAccess.Setup(m => m.smokeTest(0, 0)).Returns(20);
如果参数为 0 和 0,此设置会告诉最小起订量 return 20,否则它将 return int 的默认值再次为 0。这不是您打算创建的行为,因此在将它们传递到最小起订量设置之前,您不应将 It.IsAny<int>()
分配给 x 和 y。
正如@Rob 评论指出 It.IsAny<T>
是一种存根,您可以将其传递到最小起订量设置中,设置方法将知道如何使用 Expression Trees 处理它,但此方法实际上 returns 始终是 T 的默认值。这就是为什么我们必须始终直接在最小起订量设置中使用此方法的原因。
Moq 新手,这是一个非常简单的示例。我想模拟对我的方法 "string getCode(int someID)" 中使用的 "int smokeTest(int a, int b)" 方法的调用。 smokeTest 的变量在 getCode 中声明和设置。问题是当我模拟对 smokeTest 的方法调用时,我总是在 getCode 中得到“0”的结果,但我想看到我的预定义结果“20”。我发现的唯一解决方法是重载该方法并传入所有变量。但是,我不想这样做,因为我要测试的许多方法都声明并使用局部变量。使用最小起订量测试此方法的最佳方法是什么?谢谢
// 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");
}
仅当您将 It.IsAny<int>()
直接传递到最小起订量设置时才会起作用:
_mockDataAccess.Setup(m => m.smokeTest(It.IsAny<int>(), It.IsAny<int>())).Returns(20);
我在浏览最小起订量源代码时发现这样做:
int x = It.IsAny<int>();
int y = It.IsAny<int>();
_mockDataAccess.Setup(m => m.smokeTest(x, y)).Returns(20);
会将 x 和 y 指定为 int 的默认值,即 0,因此您的设置等同于:
_mockDataAccess.Setup(m => m.smokeTest(0, 0)).Returns(20);
如果参数为 0 和 0,此设置会告诉最小起订量 return 20,否则它将 return int 的默认值再次为 0。这不是您打算创建的行为,因此在将它们传递到最小起订量设置之前,您不应将 It.IsAny<int>()
分配给 x 和 y。
正如@Rob 评论指出 It.IsAny<T>
是一种存根,您可以将其传递到最小起订量设置中,设置方法将知道如何使用 Expression Trees 处理它,但此方法实际上 returns 始终是 T 的默认值。这就是为什么我们必须始终直接在最小起订量设置中使用此方法的原因。