为什么模拟 Repository 需要虚函数,而模拟 IRepository 会覆盖现有函数?

Why mocking a Repository requires a virtual function and mocking IRepository overrides the existing function?

我正在使用 NUnit 和 Moq 框架进行单元测试。当我尝试使用 mockRepo.Setup(x=>x.GetStr(It.IsAny)()).Returns(str) 模拟 IRepository 时,将要测试的方法得到在 Repository class 中被覆盖,构建失败。但是,如果我模拟 Repository 将要测试的方法作为虚拟方法,而不是模拟 IRepository,那么数据将被模拟并且测试运行。

任何类型的模拟都依赖于可覆盖的成员。您的 mocking-framework 将创建一些 class 来实现您的界面或覆盖您的 class。那么框架创建的内容类似于以下内容:

class WeirdClassName : IRepository
{
    string GetString(object o) => "SomeString";
}

或者如果您的会员是 class-member 这个:

class WeirdClassName : Repository
{
    string override GetString(object o) => "SomeString";
}

Interface-members 是隐式可覆盖的,因为它们实际上不提供 any 自己的逻辑。你总是可以为它提供你自己的实现。 Class-members 只有在 virtual.

时才可覆盖

在您的情况下,测试似乎有所不同,具体取决于您是模拟接口还是模拟 class。这可能表明您的测试取决于 class 的某些内部结构 - 例如回购协议上的一些初始化。您也应该模拟它,或者将您的测试与该依赖关系分离。