【发布时间】:2021-04-09 03:38:36
【问题描述】:
我有一个不是我写的类,我需要测试它的私有字段。 (不是我的选择。)
public static class ArrayPool<T>
{
public static void Return(T[] array)
{
PushTask = Task.Run(() =>
{
var bucketIndex = (int)Math.Log(array.Length, 2.0) - 6;
Buckets[bucketIndex].Push(array);
});
}
static ArrayPool()
{
Buckets = new List<ConcurrentStack<T[]>>(25);
for (int i = 0; i < 25; ++i)
Buckets.Add(new ConcurrentStack<T[]>());
}
private static readonly List<ConcurrentStack<T[]>> Buckets;
public static Task PushTask; // I added this field.
}
我为这个类写了以下测试:
[TestClass]
public class ArrayPoolTesting
{
[TestMethod]
public void ArrayPool_Return()
{
// Act
ArrayPool<int>.Return(new int[268435456]);
// Assert
if (ArrayPool<int>.PushTask.Wait(100))
{
PrivateType pt = new PrivateType(typeof(ArrayPool<int>));
var buckets = (List<ConcurrentStack<int[]>>)pt.GetStaticField("Buckets");
Assert.AreEqual(25, buckets.Count);
Assert.AreEqual(1, buckets[22].Count);
}
}
}
但是,它每次都失败。它在测试的if条件中抛出了一个空引用异常,因为ArrayPool<int>.PushTask是null。 (实际上,它在我的工作计算机上每次都失败。在我编写此精简版本的家用计算机上,它每次都有效。但我已经梳理了这两个程序,我相信它们本质上是相同的。)我不想修改原来的类,但我确实添加了 public PushTask 字段,希望使类可测试。
我明白为什么它失败了。在方法中的任务完成并将其值分配给Task 字段之前,它会到达测试中的if 条件。增加Wait时间无济于事。
- 有什么方法可以挽救这种方法吗?
- 有没有更好的方法来解决这个问题?
我从调试中知道Return 方法工作正常,但我无法对其进行测试,因为断言在Task 字段被初始化之前运行。
【问题讨论】:
-
原来的
Return方法是使用Task还是你添加的? -
原来使用的是任务。我添加了 PushTask 字段和 Task.Run 返回值的分配给它。
-
如果可以的话,重构代码并一路异步。或一路同步。混合它们只是自找麻烦。
-
但无论如何都要让测试异步并等待任务。
-
仅供参考谁曾经写过这个方法。 ArrayPool 是一个非常糟糕的名字。此外,您应该测试行为而不是实现和内部状态。最后,这整个类是不确定的并且不是线程安全的,并且无论测试如何,将来都会被某人破坏
标签: c# unit-testing task