C# 对数据流网格进行单元测试
一、问题
假设在应用程序中有数据流网格,你需要确认它正常工作。
二、解决方案
数据流网格是独立的,它有自己的寿命,且本质上是异步的。因此,要测试数据流网格,最自然的方法是异步单元测试:
[TestMethod]
public async Task MyCustomBlock_AddsOneToDataItems()
{
var myCustomBlock = CreateMyCustomBlock();
myCustomBlock.Post(3);
myCustomBlock.Post(13);
myCustomBlock.Complete();
Assert.AreEqual(4, myCustomBlock.Receive());
Assert.AreEqual(14, myCustomBlock.Receive());
await myCustomBlock.Completion;
}
然而,单元测试的失败并不会非常直接。这是因为,每当数据流网格中的异常传递到下一个数据流块时,就会被包装在另一个 AggregateException
中。下例使用了辅助方法来确保异常会丢弃数据并通过自定义块传递。
[TestMethod]
public async Task MyCustomBlock_Fault_DiscardsDataAndFaults()
{
var myCustomBlock = CreateMyCustomBlock();
myCustomBlock.Post(3);
myCustomBlock.Post(13);
(myCustomBlock as IDataflowBlock).Fault(new InvalidOperationException());
try
{
await myCustomBlock.Completion;
}
catch (AggregateException ex)
{
AssertExceptionIs<InvalidOperationException>(
ex.Flatten().InnerException, false);
}
}
public static void AssertExceptionIs<TException>(Exception ex,
bool allowDerivedTypes = true)
{
if (allowDerivedTypes && !(ex is TException))
Assert.Fail($"Exception is of type {ex.GetType().Name}, but " +
$"{typeof(TException).Name} or a derived type was expected.");
if (!allowDerivedTypes && ex.GetType() != typeof(TException))
Assert.Fail($"Exception is of type {ex.GetType().Name}, but " +
$"{typeof(TException).Name} was expected.");
}
三、讨论
直接对数据流网格进行单元测试是可行的,但会有些笨拙。如果网格是某个更大组件的一部分,那么或许直接对这个大组件进行单元测试会更为方便(隐式测试网格)。如果开发的是可复用的自定义块或网格,那么应当采用上面的这些单元测试。
(完)
相关阅读:
C# 对 async 方法进行单元测试
C# 对预期失败的 async 方法进行单元测试
C# 对 async void 方法进行单元测试
C# 对数据流网格进行单元测试
C# 对 System.Reactive 可观察对象进行单元测试
C# 通过伪造调度对 System.Reactive 可观察对象进行单元测试
评论
发表评论