我有一个应用程序服务(即大型方法)负责协调多个业务对象之间的交互。从本质上说,它需要一个包含客户信息和发票的系统的DTO,并根据各种业务规则将其翻译并导入到不同的系统中。正确处理单元测试“复杂”应用程序服务
public void ProcessQueuedData()
{
var queuedItems = _importServiceDAL.LoadQueuedData();
foreach (var queuedItem in queuedItems)
{
var itemType = GetQueuedImportItemType(queuedItem);
if (itemType == QueuedImportItemType.Invoice)
{
var account = _accountDAL.GetAccountByAssocNo(queuedItem.Assoc);
int agentAccountID;
if (!account.IsValid)
{
agentAccountId = _accountDAL.AddAccount(queuedItem.Assoc);
}
else
{
agentAccountId = account.AgentAccountID;
}
/// Do additional processing TBD
}
}
}
对于单元测试,它是正确的假设的服务内的整个过程中应在粒状步步基础进行测试,类似于以下?
ImportService_ProcessQueuedData_CallsDataAccessLayer_ToLoadQueue
ImportService_ProcessQueuedData_WithQueuedItemToProccess_ChecksIfAccountExists
ImportService_ProcessQueuedData_WithInvoice_CallsDALToCreateAccountIfOneDoesNotExist
下面是一个典型的测试:
[TestMethod()]
public void ImportService_ProcessQueuedData_WithInvoice_CallsDALToCheckIfAgentAccountExists()
{
var accountDAL = MockRepository.GenerateStub<IAccountDAL>();
var importServiceDAL = MockRepository.GenerateStub<IImportServiceDAL>();
importServiceDAL.Stub(x => x.LoadQueuedData())
.Return(GetQueuedImportItemsWithInvoice());
accountDAL.Stub(x => x.GetAccountByAssocNo("FFFFF"))
.IgnoreArguments()
.Return(new Account() { AgentAccountId = 0 });
var importSvc = new ImportService(accountDAL, importServiceDAL);
importSvc.ProcessQueuedData();
accountDAL.AssertWasCalled(a => a.GetAccountByAssocNo("FFFFF"), o => o.IgnoreArguments());
accountDAL.VerifyAllExpectations();
}
我的问题是我最终在这些测试中做了这么多设置,它变得很脆弱。这是否是正确的方法,如果是的话,在每个粒度测试中避免重复所有这些设置的指针是什么?
谢谢吉安...你建议NModel B/C可能的输入条件的感知数量是巨大的?如果输入类型的组合更受限制,您是否仍然会推荐这种方法?我试图测试的整个过程实际上只有6个条件分支和已知数量的条件在这个if-then逻辑中发挥作用。再次感谢您的洞察力。 – nerdn 2010-07-22 12:44:40
它更像是一个连续的过程,在每一步都有可能出现错误情况,并且可能有通过这些行为的多种不同途径。这就是基于模型的测试真正闪耀的地方 - 您只需对模型中的所有状态进行编码,并让测试系统找出可能的路径。 – Gian 2010-07-22 13:02:11