我是以正确的方式来做这件事的吗?如果是这样,我能正确理解吗?我有点困惑。
我的项目设置在三个不同的层中。 UI层,业务层和数据访问层。业务层和数据访问层都是基于接口构建的。
我正在尝试使用NUnit和Moq编写单元测试。
这是我的例子。我想测试GetSum(int x,int y),这是一个只返回x + y的简单函数。此函数存在于CalculatorLogic中,并实现ICalculatorLogic。
public class CalculatorLogic : ICalculatorLogic
{
public int GetSum(int x, int y)
{
return x + y;
}
}
现在,我正在尝试编写UnitTest。
[TestFixture]
public class CalculatorLogicTests
{
Mock<ICalculatorLogic> calculatorLogicMock;
ICalculatorLogic calculatorLogic;
public CalculatorLogicTests()
{
calculatorLogicMock = new Mock<ICalculatorLogic>();
// now i need to do this setup, right?
calculatorLogicMock.Setup(x => x.GetSum(It.IsAny<int>(), It.IsAny<int>())).Returns(6);
calculatorLogic = calculatorLogicMock.Object;
}
[Test]
public void GetSum_Test()
{
int expectedResult = 3 + 3;
var sum = calculatorLogic.GetSum(3, 3);
Assert.AreEqual(sum, expectedResult);
}
}
现在,上述通过。它运行,它得到了我所期待的。但是,感觉不对。它只是返回我设置它在Setup()调用中返回的任何内容。如果我在Returns()而不是6中放了一个3,它就会失败。
我必须理解错误。否则,如果我告诉它要返回什么,我是否真的在测试我的功能?
答案 0 :(得分:0)
好的,你有一个接口ICalculatorLogic
和你希望为其编写测试的所谓接口CalculatorLogic
的实现。
您正在使用模拟框架Moq
来模拟CalculatorLogic
没有的依赖项。你应该写这样的东西:
[TestFixture]
public class CalculatorLogicTests
{
// Our unit under test.
ICalculatorLogic calculatorLogic;
[SetUp]
public void SetUp()
{
// This method is called for every [Test] in this class.
// So let's recreate our CalculatorLogic here so that each
// test has a fresh instance.
calculatorLogic = new CalculatorLogic();
}
[Test]
public void GetSum_WithTwoIntegers_ReturnsTheirSum()
{
// Arrange
int expectedResult = 3 + 3;
// Act
var sum = calculatorLogic.GetSum(3, 3);
// Assert
Assert.AreEqual(sum, expectedResult);
}
}
现在让我们假设您希望GetSum
记录调用它的参数。您可以像这样创建一个记录器界面:
public interface ILogger {
void Log(int x, int y);
}
然后通过在CalculatorLogic
类的构造函数中要求它将其作为依赖项:
public class CalculatorLogic : ICalculatorLogic
{
private readonly ILogger logger;
// Now we have a dependency on ILogger!
public CalculatorLogic(ILogger l) {
logger = l;
}
public int GetSum(int x, int y)
{
// Let's log those numbers!
logger.Log(x, y);
return x + y;
}
}
然后你可以这样编写你的测试(使用Moq
):
[TestFixture]
public class CalculatorLogicTests
{
// This guy we want to test.
ICalculatorLogic calculatorLogic;
// Our mock!
Mock<ILogger> loggerMock;
[SetUp]
public void SetUp()
{
// Create the logger mock!
loggerMock = new Mock<ILogger>();
// Inject the logger into our CalculatorLogic!
calculatorLogic = new CalculatorLogic(loggerMock.Object);
}
[Test]
public void GetSum_WithTwoIntegers_ShouldCallLogger()
{
// Arrange
int expectedResult = 3 + 3;
// Act
var sum = calculatorLogic.GetSum(3, 3);
// Assert
Assert.AreEqual(sum, expectedResult);
// Verify that the logger's Log method was called once with x = 3 and y = 3.
loggerMock.Verify(logger => logger.Log(It.Is<int>(x => x == 3), It.Is<int>(y => y == 3)), Times.Once());
}
}