我有一个控制器类,它在ctor中接受多个参数,这些参数在运行时被注入。
示例:
public ProductController(IProductRepositort productRepository,
IShippingService shippingService, IEmailProvider emailProvider)
{
...
}
我发现测试方法变得越来越大。我正在设置如下方法:
[Test]
public void CanSendProduct()
{
//Code to set up stub
List<Product> products = new List<Product>();
for (int i = 0; i < length; i++)
{
products.Add(new Product()));
}
var mockProductRepository = new Mock<IProductRepository>();
mockProductRepository.Setup(x => x.GetProducts()).Returns(products);
//Code to set up stub
....
....
var mockShippingService = new Mock<IShippingService>();
mockShippingService.Setup(x => x.GetShippers()).Returns(shippers);
//Code to set up stub
.....
.....
var mockEmailProvider = new Mock<IEmailProvider>();
mockEmailProvider.Setup(x => x.Send()).Returns(provider);
//Execute Test
....
....
//Assert
....
....
}
显然,在此测试类的每个方法中重复模拟设置是不切实际的。
如何创建丰富的模拟对象,使我能够对我的测试进行行为验证,同时最大限度地减少设置难度?
处理此问题的TDD最佳做法是什么?
由于
答案 0 :(得分:6)
如果您的测试框架支持将在每次测试之前和之后调用的setup / teardown函数,请在这些函数中创建并销毁一些“默认”模拟对象。您的测试可以简单地使用它们,对于默认模拟对象不适合您的特殊情况,您可以简单地忽略它们并在这些测试中创建本地模拟对象。
答案 1 :(得分:0)
使用行为或功能测试套件。看起来像你的C#或Java?无论哪种方式,我都会推荐FItnesse,但还有其他人。至于单元测试,我可能会使用像Winsor / Castle或Spring这样的IOC容器,然后你可以为填充Mocks而不是“真实”对象的测试设置一个容器。
答案 2 :(得分:0)
我只是将这些代码提取到方法中(如果你的模拟框架要求你传递模拟工厂,根据需要更改签名):
private Mock<IProductRepository> SetupStandardMockProductRepository() {
List<Product> products = new List<Product>();
for (int i = 0; i < length; i++) {
products.Add(new Product()));
}
var mockProductRepository = new Mock<IProductRepository>();
mockProductRepository.Setup(x => x.GetProducts()).Returns(products);
}
// ... and so forth
然后,在你的测试中:
var mockProductRepository = SetupStandardMockProductRepository();
// or make these static properties of some central test class, like this:
var mockProductRepository = Stubs.StandardProductRepository;