gpt4 book ai didi

C#多线程单元测试

转载 作者:太空宇宙 更新时间:2023-11-03 13:19:59 26 4
gpt4 key购买 nike

我正在寻找有关在 C# 中为多线程编写单元测试的一些建议。具体来说,我想检查一个对象是否被正确锁定。但是,为了对此进行测试,我需要针对该对象进行断言,该对象可能在实现断言之前已更改(释放锁后,另一个线程可能会更改该对象)。

使用 AutoResetEvent 我已经能够控制单元测试端的流程,让我能够有效地模拟测试对象中的锁。这个问题是我不再需要锁来让测试通过。

我想要的是有一个在锁定时通过并在锁定时失败的测试。

显然,这是一个简化的示例。它也是 .Net 4,所以没有 asyncawait 选项(尽管如果这有帮助,更改可能是一个选项)。

欢迎提出建议。谢谢。

示例代码如下:

    public class BasicClass
{
public int Val
{
get { lock (lockingObject) { return val; } }
private set { lock (lockingObject) { val = value; } }
}
private int val;

public BasicClass(int val = -1)
{
Val = val;
}

public void SetValue(int val)
{
Val = val;
}
private object lockingObject = new object();
}

这是 (NUnit) 单元测试:

    [Test]
public void BasicClassTest()
{
for (int repeat = 0; repeat < 1000; repeat++) // Purely for dev testing and can get away with as no SetUp/TearDown
{
BasicClass b = new BasicClass();

int taskCount = 10;
Task[] tasks = new Task[taskCount];

var taskControl = new AutoResetEvent(false);
var resultControl = new AutoResetEvent(false);
int expected = -1;

for (int i = 0; i < taskCount; i++)
{
int temp = i;
tasks[temp] = new Task(() =>
{
taskControl.WaitOne(); // Hold there here until set
b.SetValue(temp);
expected = temp;
resultControl.Set(); // Allows asserts to be processed.
});
}

// Start each task
foreach (var t in tasks)
t.Start();

// Assert results as tasks finish.
for (int i = 0; i < taskCount; i++)
{
taskControl.Set(); // Unblock, allow one thread to proceed.
resultControl.WaitOne(); // Wait for a task to set a expected value
Assert.That(b.Val, Is.EqualTo(expected));
Console.WriteLine("b.Val = {0}, expected = {1}", b.Val, expected); // Output values to ensure they are changing
}

// Wait for all tasks to finish, but not forever.
Task.WaitAll(tasks, 1000);
}
}

最佳答案

至于 DateTime.Now 等其他系统函数,我更喜欢抽象线程函数,如 sleep、mutex、signals 等等(是的,我知道有 DateTime.Now 和其他系统函数的库,但我想抽象这是一个更好的方法)。

因此,您最终会得到一种带有 Sleep 等方法的 IThreadind 接口(interface)。缺点是,在这种情况下您不能使用方便的 lock 语句。您可以使用 Lock(object) 方法返回一个 IDisposable,您可以将其与“using”语句一起使用,以获得几乎相同的舒适度。

using(threading.Lock(lockObject))
{
...
}

现在您可以使用真实函数创建真实实现,并为注入(inject)的单元测试创​​建 Mock。因此,例如,您可以在测试中将任何 sleep 调用缩短到几毫秒,以加快测试速度。并且您可以验证是否调用了您期望的所有函数。

听起来工作量很大?想一想,您将花费多少时间来调试一些讨厌的线程问题,这些问题有时会导致您的生产系统崩溃,而您的客户会胡作非为。

关于C#多线程单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24679027/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com