[英]How to test race condition with async unit tests using NUnit?
这是我要测试的赛车条件代码,我有一个遗留代码,可以在一定程度上进行更改。 在我的主要函数中,我有一个函数可以返回我们等待的Task,另一个UI不能因为其运行在另一个线程上而被阻止的函数。
在原始代码中,我们不在乎结果,我们只是在初始化一些类,我测试了ViewModel不为null。
在我在此处提供的示例代码中,我更改了代码以例证竞争条件的问题。 目前,我的测试将失败。 如何正确测试我的赛车状况 ?
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Myclass tempClass = new Myclass();
tempClass.CreateImage();
Assert.AreEqual(3, tempClass.Sum);
}
}
public class Myclass
{
public int Sum;
public Myclass()
{
Sum = 0;
}
public async Task CreateImage()
{
await InternalFunction();
await Task.Run(() => Physics());
}
public async Task InternalFunction()
{
await Task.Run(() =>
{
Math();
});
}
public void Math()
{
Sum += 1;
}
public void Physics()
{
Sum += 2;
}
}
如果运行测试,sum属性将为1,而不是预期的3。 我如何更改代码以能够执行CreateImage()
函数的所有流程,并且仅在完成所有线程后,我才需要声明TempClass的结果/内容。
CreateImage
方法是异步的,但是您的单元测试方法不是,因此您的测试可能在CreateImage完成之前完成。
您没有指定要使用的NUnit版本,但是以下内容在NUnit 3的最新版本中有效
[TestFixture]
public class UnitTest1
{
[Test]
public async Task TestMethod1()
{
Myclass tempClass = new Myclass();
await tempClass.CreateImage();
Assert.AreEqual(3, tempClass.Sum);
}
}
当然,这假设MyClass
是线程安全的-如果您的实际代码使用多个线程同时修改MyClass
实例的状态,那么您可能还需要考虑使用同步机制,例如BCL中内置的一种同步机制-https ://docs.microsoft.com/zh-cn/dotnet/standard/threading/synchronizing-data-for-multithreading
另外,您可能会考虑使用由Stephen Cleary开发的一些异步友好的帮助器-https: //github.com/StephenCleary/AsyncEx
您也必须等待测试中的代码,否则,Aseert将在代码完成之前进行:
[TestMethod]
public async Task TestMethod1()
{
Myclass tempClass = new Myclass();
await tempClass.CreateImage();
Assert.AreEqual(3, tempClass.Sum);
}
但是对我来说,这段代码有一些不足之处。 Task.Run
有很多包装同步代码的Task.Run
,但现在不会带来任何好处。 同样, Sum
也不是线程安全的,因此,如果在任何时间点, Sum
都会被线程访问,则可能会发生并发的不良事件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.