目前,我正致力于开发相当多报告风格的系统,这些功能消耗许多不同的数据点,并将它们转换为更大的,有时是扁平化的输出。我的大多数应用程序都是基于存储库模式的变体。因此,我有一套模拟存储库,用于测试场景。我遇到的问题是这些数据点之间的交互非常复杂,很快就成为维护“模拟数据”的维护噩梦。这是一个模拟的例子:
public class SomeReportingEntity
{
private IProductRepo ProductRepo;
private IManagerRepo ManagerRepo;
private ILocationRepo LocationRepo;
private IOrdersService OrdersService;
private IEmployeeRepo EmployeeRepo;
public ReportingEntity(IProductRepo ipr, IManagerRepo imr, ILocationRepo ilr, IOrdersService ios,
IEmployeeRepo ier){
//Load these to private vars...
}
//This is the function that I want to test...
public SomeReportingEntity GetManagerSalesByRegionReport()
{
//Make a complex join on all sub collections. These
//sub collections are all under test individually.
var MangerSalesByRegionItems = From x in ProductRepo.CurrentProducts()
Join y in OrdersService.FutureOrders() On ...
Join z in EmployeeRepo.ActiveEmployees() On ...
Join a in LocationRepo.GetAllRegions() On ...
Join b In ManagerRepo.GetActiveManagers On ...
Select new SomeReportingEntity() With { ... }
return MangerSalesByRegionItems.ToList();
}
}
不可否认,这是一个非常人为的例子,但我想强调的基本思想是我有几个我正在加入的存储库,我需要创建许多测试来确保这个复杂的查询按预期进行。由于连接操作非常复杂,它使得模拟数据非常难以保持一致 - 特别是因为我必须添加更多关联并测试其他点。此外,我需要能够在模拟中输入特定的记录状态(例如缺少分配的经理的员工)来验证查询是否正确处理这些情况。
所以这是我的问题:
答案 0 :(得分:1)
我自己一直致力于数据量大的项目。对我们有用的是使用Repository本身来水合对象,然后将它们序列化为XML。我们将XML文件放入我们的测试项目中,并将其作为自动化测试的起点。这很好,因为它可以确保您的模拟数据看起来像真实的数据。
我们的测试看起来像这样...
var object1 = XmlUtil.LoadObject1("filename1");
var object2 = XmlUtil.LoadObject2("filename2");
var result = SomeConverter.Convert(object1, object2);
Assert("somevalue", result.Property1);
如果您需要进行内联查找,可以添加一个模拟存储库,该存储库将提供相同级别的依赖注入。
此方法的缺点是数据架构是否发生变化。有时,如果数据模式已更改,则测试可能会过时。如果您的架构仍然存在很大的变化,我会保持您的自动化测试很小,直到架构稳定下来。专注于单元测试,直到您知道模式相对稳定。
答案 1 :(得分:1)
您要做的第一件事是制作集中对象,知道如何检索不同存储库的数据。由于这只是报告,因此您更容易,因为您不必担心更改跟踪。
从后勤角度来看,我要考虑的一件事是建立一个本地数据库来保存远程数据(使用代理定期更新)。这将消除一些调用远程服务和动态聚合数据的问题。您还可以在开始时预处理一些数据。
当我使用存储库模式时,我将其与Unit Of Work pattern结合使用。工作单位是为你做所有腿部工作的人。从理论上讲,您的UoW可以从多个服务中引入数据,并根据配置将其呈现给存储库。
为了进行测试,您可以使用InMemoryUnitOfWork在一个地方提供所有数据。
答案 2 :(得分:-1)
您必须准确决定要测试的内容。
这样做的一种方法可能是假装你正在使用TDD。假设您的GetManagerSalesByRegionReport
方法不存在(或实际删除它)。你必须:
void
,因为您的测试不需要它返回任何内容。List
,即使所有子存储库都没有数据。null
。您的测试仍然会失败,因此将其更改为返回空的List
并且它将通过。还剩下什么?这些是INNER
连接,因此除非所有存储库至少包含一行,否则您将不会获得任何数据。因此,测试一下:创建一个测试,其中每个repo包含一行,并确保返回的列表包含适当的行数。然后,测试每个返回行的相应属性。然后测试如果任何repos不包含任何行,则不返回任何数据。
然后,如果一些回购包含多行,可能会测试会发生什么。
然后,我不知道还有什么可以测试。