为真实对象创建代理
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);
注意:您需要遗留代码测试技术这一事实可能表明代码有异味。作为第一步,我建议将断言模拟的测试与断言真实实现结果(持久层中的更改)的测试分开。
我想使用真实存储库编写集成测试,但也想验证存储库的行为
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);
注意:您需要遗留代码测试技术这一事实可能表明代码有异味。作为第一步,我建议将断言模拟的测试与断言真实实现结果(持久层中的更改)的测试分开。