[英]How can I test that implementations are synchronous or asynchronous where required to be so?
I'm trying to write unit tests around a custom SynchronizationContext
implementation. 我正在尝试围绕自定义
SynchronizationContext
实现编写单元测试。
The two important operations on this class are Send
and Post
, where Send
invokes a delegate synchronously and Post
invokes a delegate asynchronously. 此类上的两个重要操作是
Send
和Post
,其中Send
同步调用委托, Post
以异步方式调用委托。
I would like to write unit tests to verify this behaviour, that the delegates were executed synchronously or asynchronously. 我想编写单元测试来验证这种行为,代理是同步还是异步执行的。 I don't want the tests to rely on delays for success cases, because it artificially prolongs the tests running (but it's reasonable to have failures cause a delay) in execution.
我不希望测试依赖于成功案例的延迟,因为它人为地延长了测试的运行时间(但是在故障导致延迟的情况下是合理的)。
Initially I have considered using Tasks to signal the execution of a delegate: 最初我考虑使用Tasks来表示委托的执行:
var tcs = new TaskCompletionSource<object>();
var context = new CustomSynchronizationContext();
context.Send((state) => tcs.SetResult(null), null);
// Task should already be completed!
Assert.IsTrue(this.tcs.Task.IsCompleted);
However, this does not ensure the delegate was not executed asynchronously very quickly before the test runner could continue. 但是,这并不能确保在测试运行器继续之前不会非常快速地异步执行委托。
How can I arrange a test around the context to ensure that Send
blocks for the completion of the delegate and Post
does not, but that the delegates are both invoked? 我如何安排围绕上下文中的测试,以确保
Send
块为代表的完成和Post
没有,但代表们都调用?
I believe you can achieve this using a pair of ManualResetEvents . 我相信你可以使用一对ManualResetEvents来实现这一点。 Using the code below, the slow down is only experienced if the tests failed (the numbers are pretty high and could probably be reduced safely).
使用下面的代码,只有在测试失败时才会出现减速(数字非常高并且可能安全地减少)。 The idea here is that we assert the order in which things must occur that can only happen if we block or don't block.
这里的想法是我们断言必须发生的事情的顺序,只有在我们阻止或不阻止时才会发生。
For the synchronous test: 对于同步测试:
var incall = new ManualResetEvent(false);
var unblock = new ManualResetEvent(false);
var context = new CustomSynchronizationContext();
var t = Task.Run(() => context.Send(state =>
{
incall.Set();
unblock.WaitOne(5000);
}, null));
Assert.IsTrue(incall.WaitOne(1000));
Assert.IsFalse(t.Wait(10));
unblock.Set();
Assert.IsTrue(t.Wait(1000));
for the Async test: 对于异步测试:
var incall = new ManualResetEvent(false);
var unblock = new ManualResetEvent(false);
var context = new CustomSynchronizationContext();
var t = Task.Run(() =>context.Post(state =>
{
incall.Set();
unblock.WaitOne(5000);
}, null));
Assert.IsTrue(incall.WaitOne(1000));
Assert.IsTrue(t.Wait(1000)); //This will timeout if unblock is blocking completion of the task
unblock.Set();
Incorporating my idea: 结合我的想法:
var mainThreadId = Thread.ManagedThreadId;
var sendThreadId;
context.Send((state) => sendThreadId = Thread.ManagedThreadId);
Assert.AreEqual(mainThreadId, sendThreadId);
Don't know if this actually works, you'll have to check. 不知道这是否真的有效,你必须检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.