我们遇到的问题是,在TeamCity的CI期间,我们的一个单元测试失败了几天。我们使用MSTest和RhinoMocks。在dev机器上重现它几乎是不可能的(也许是因为开发机器上有1台cpu PC,我不知道)。
[TestMethod]
[TestCategory("UnitTest")]
[ExpectedException(typeof(AggregateException))]
public void TestRiskDataStagingThrowAggregateException()
{
DataStagingThrowException(typeof(DeskRiskDataPump));
}
protected void DataStagingThrowException(Type dataPumpType)
{
// set expectations
foreach (IUploader uploader in StubUploaders)
{
uploader.Expect(x => x.Upload(StubDataProvider)).Repeat.Once().Throw(new Exception("BANG!!!"));
}
Repository.ReplayAll();
IDataPump datapump = new DataPumpFactory().GetDataPump(dataPumpType, StubDataProvider, StubUploaders, StubDistributor);
// Execute
// the test can hang here!!!
datapump.Execute();
Repository.VerifyAll();
}
StubDataProvider = Repository.Stub<IEnumerable<TRecord>>();
StubUploaders = new List<IUploader>();
StubDistributor = Repository.Stub<IDataDistributor>();
StubUploaders.Add(Repository.Stub<IUploader>());
StubUploaders.Add(Repository.Stub<IUploader>());
StubUploaders.Add(Repository.Stub<IUploader>());
实现IDataPump
的类有点复杂,我害怕在这里发布:)一般来说它实现了Producer-Consumer模式并在不同的流中启动了一些进程,像这样
Task[] tasks = new Task[4];
// Start adding to the queue
tasks[0] = Task.Factory.StartNew(Produce);
// Start draining the queue in parallel
tasks[1] = Task.Factory.StartNew(ConsumeCreditRisk);
tasks[2] = Task.Factory.StartNew(ConsumeTrancheRisk);
tasks[3] = Task.Factory.StartNew(ConsumeRatesRisk);
// Wait to complete
try
{
Task.WaitAll(tasks);
}
catch (AggregateException e)
{
.....
throw;
}
private void ConsumeCreditRisk()
{
_creditRiskUploader.Upload(_creditRiskBuffer.GetConsumingEnumerable());
}
在我们的例子中,上传者是假设抛出异常的存根,它应该作为聚合异常捕获。但根据日志,它有时会挂在存根方法上传。
您有什么建议会导致问题吗?
答案 0 :(得分:1)
实际上,您需要为任何多线程测试提供超时,以防止死锁搞砸您的构建。这是一种解决方法。