为真实对象创建代理

Creating proxies for real objects

我想使用真实存储库编写集成测试,但也想验证存储库的行为

SomeService(IRepository r) 呼叫 r.QuerySomething()

我一直在尝试使用最小起订量来实现这一点:

var mock = new Mock<IRepository >(() => new Repository());
mock.CallBase = true;

问题是它从不从 Repository 调用方法,也不调用它的构造函数。那里的 lambda 用于获取 ctor 参数(如果类型是 class)而不是用于对象初始化。

问:如何将 new Repository() 包装到 Mock<IIRepository> 中以便验证调用?

注意:如果给定的类型是 class,它会起作用,但我不能用它来验证,因为它们的实现不是虚拟的。

或者还有其他一些 nuget 可以帮助我实现这个目标吗?

我使用一种技术来测试 brownfiled 遗留代码,它可能会帮助您实现目标。你可以在你的测试项目中引入一个装饰器来包装你的原始实现,但也实现了 IRepository 接口。

class TestRepository : IRepostiory
{
   public TestRepository(Repository next)
   {
      this.next = next;
   }
}

在此 class 中,您可以将所有 interface 成员声明为 virtual

class TestRepository : IRepostiory
{
   public virtual IReadOnlyList<Client> GetByName(string name) 
   { 
      return this.next.GetByName(name);
   }
}

现在您可以使用 TestRepository 代替您的原始实现,还可以创建一个模拟来验证对此 class.

的调用
var repository = new Repository();
var sutMock = new Mock<TestRepository>(repository) { CallBase = true };
var sut = sutMock.Object;

sut.GetByName("John Doe");

sutMock.Verify(x => x.GetByName("John Doe"), Times.Once);

注意:您需要遗留代码测试技术这一事实可能表明代码有异味。作为第一步,我建议将断言模拟的测试与断言真实实现结果(持久层中的更改)的测试分开。