使用 Moq 毫无意义,因为 Returns() 重新定义了您的方法的行为?

Is using Moq pointless, since Returns() redefines the behavior of your method?

我正在尝试熟悉 TDD。我想弄清楚如何将 Moq 与 NUnit 一起使用。我创建了一个 ICalculator 接口,它有一个 Add(decimal num1, decimal num2) 方法和一个实现它的计算器 class。

我的问题是,通过指定输入特定值时应返回的内容,我是否基本上没有重新定义我的方法的工作方式?我的意思是,如果我突然让 Add 方法改为乘以数字,我的测试仍然不会中断,因为我已经完全改变了它的工作方式。

关于最小起订量的用途及其使用方式,我是否遗漏了一些明显的信息?

 var mockCalculator = new Mock<ICalculator>();
 mockCalculator.Setup(mock => mock.Add(10m, 25m)).Returns(35m);
 var calculator = mockCalculator.Object;

 var result = calculator.Add(10m, 25m);

 Assert.That(result, Is.EqualTo(35m));

我也尝试按照文章 here 进行操作,但它最终做了同样的事情 - 预定义的结果即使被测试的方法发生变化也不会改变。

模拟的重点不是模拟您正在测试的中央代码,而是模拟其依赖项。当依赖项是接口时,这最有效。假设您有这个界面:

public interface IFileLoader {
    string loadFileContents(string fileName);
}

和一个 class 通过实际打开和读取该文件来实现它。然后,您有另一个 class 使用 class:

public class FileAnalyzer {
    private readonly IFileLoader _fileLoader;

    public FileAnalyzer(IFileLoader fileLoader) {
        _fileLoader = fileLoader;
    }

    public string Analyze(string fileName) {
        String contents = _fileLoader.loadFileContents(fileName);
        // (Some fancy algorithm here, resulting in some return value)
    }
}

现在,您要测试 FileAnalyzer.Analyze(),其中可能包含一些高级逻辑。实际上必须在磁盘上创建一个文件并在测试期间将其传递给该方法是很麻烦的;简单地将输入字符串保存在变量中会更容易。使用模拟框架,您可以模拟依赖项FileLoader,从而能够专注于测试实际逻辑。

[Test]
public void TestAnalyze() {
    var mockLoader = new Mock<IFileLoader>();
    mockLoader.Setup(ml => ml.loadFileContents("foo.txt")).Returns("Whatever you would have had in the file");
    var analyzer = new FileAnalyzer(mockLoader.Object);
    Assert.That(analyzer.Analyze("foo.txt"), Is.EqualTo("Expected analysis result"));
}

此测试完全不涉及文件系统,因此更简单、更快速。在生产(非测试)代码中,您将使用 IFileLoader 的实际实现,它实际上从磁盘读取文件:new FileAnalyzer(new RealFileLoader())。另外,请注意 FileAnalyzer 不需要知道文件,也不需要知道当 运行 在生产中时它的数据将来自文件以及在测试中 运行 时它的数据将来自字符串的事实。