我正在尝试围绕异步发布/订阅系统编写单元测试。在我的单元测试中,我创建一个TaskCompletionSource<int>
并在订阅回调中为其分配一个值。在订阅回调中,我取消订阅出版物。下次我发布时,我想验证回调是否从未被击中。
[TestMethod]
[Owner("Johnathon Sullinger")]
[TestCategory("Domain")]
[TestCategory("Domain - Events")]
public async Task DomainEvents_subscription_stops_receiving_messages_after_unsubscribing()
{
// Arrange
string content = "Domain Test";
var completionTask = new TaskCompletionSource<int>();
DomainEvents.Subscribe<FakeDomainEvent>(
(domainEvent, subscription) =>
{
// Set the completion source so the awaited task can fetch the result.
completionTask.TrySetResult(1);
subscription.Unsubscribe();
return completionTask.Task;
});
// Act
// Publish the first message
DomainEvents.Publish(new FakeDomainEvent(content));
await completionTask.Task;
// Get the first result
int firstResult = completionTask.Task.Result;
// Publish the second message
completionTask = new TaskCompletionSource<int>();
DomainEvents.Publish(new FakeDomainEvent(content));
await completionTask.Task;
// Get the second result
int secondResult = completionTask.Task.Result;
// Assert
Assert.AreEqual(1, firstResult, "The first result did not receive the expected value from the subscription delegate.");
Assert.AreEqual(default(int), secondResult, "The second result had a value assigned to it when it shouldn't have. The unsubscription did not work.");
}
当我这样做时,测试挂在第二个await
。我知道这是由于任务永远不会返回而发生的。我不确定如何解决它。我知道我可以轻松地创建一个本地字段,我只需像这样分配值:
[TestMethod]
[Owner("Johnathon Sullinger")]
[TestCategory("Domain")]
[TestCategory("Domain - Events")]
public void omainEvents_subscription_stops_receiving_messages_after_unsubscribing()
{
// Arrange
string content = "Domain Test";
int callbackResult = 0;
DomainEvents.Subscribe<FakeDomainEvent>(
(domainEvent, subscription) =>
{
// Set the completion source so the awaited task can fetch the result.
callbackResult++;
subscription.Unsubscribe();
return Task.FromResult(callbackResult);
});
// Act
// Publish the first message
DomainEvents.Publish(new FakeDomainEvent(content));
// Publish the second message
DomainEvents.Publish(new FakeDomainEvent(content));
// Assert
Assert.AreEqual(1, firstResult, "The callback was hit more than expected, or not hit at all.");
}
不过这感觉不对。这假设我从未在整个堆栈中执行等待操作(当他们是订阅者时我会这样做)。此测试不是安全测试,因为测试可能会在发布完全完成之前完成。这里的意图是我的回调是异步的,并且发布是非阻塞的后台进程。
在这种情况下如何处理 CompletionSource?