如何使用 Visual Studio 的 Fakes 框架对异步方法进行存根?

Kla*_*sen 1 c# mstest stub async-await microsoft-fakes

我需要存根的方法的调用方式如下:

List<DocumentInfo> documentInfosToDelete = await _documentInfoRepository.GetListByExternalIdAsync(
    partyLegalEntity, 
    externalId,
    type,
    status);
Run Code Online (Sandbox Code Playgroud)

这有效,但会生成编译器警告:“此异步方法缺少‘等待’运算符”等。

   testService.DocumentInfoRepos.GetListByExternalIdAsyncStringStringDocumentTypeDocumentStatus =
                (async (a, b, c, d) => 
            {
                GetListByExternalIdAsyncCalled = true;
                return new List<DocumentInfo>();
            });
Run Code Online (Sandbox Code Playgroud)

我想摆脱这些警告,因为它们会淹没任何有关实际问题的警告。

返回 new Task(...) 挂起。如果我正确理解了我在 WWW 上找到的内容,Task.Run(...) 所做的事情与我们正在使用的等待异步模式完全不同。

该怎么办?

Jan*_*icz 6

@Klaus 提出了一个很好的问题,因为例如在测试期间,测试调用异步方法的代码如何表现成功、错误和取消是很好的。Task 中定义了以下内容:

  • Task Task.CompletedTask:属性,获取已经成功完成任务的Task
  • Task Task.FromException(Exception):方法,创建一个已完成但出现指定异常的任务。
  • Task Task.FromCanceled(CancellationToken):方法,使用指定的取消令牌创建由于取消而完成的任务。
  • Task Task.FromResult(T):方法,获取已经成功完成任务的Task
  • Task Task.FromException(Exception):方法,创建一个已完成但出现指定异常的任务。
  • Task Task.FromCanceled(CancellationToken):方法,使用指定的取消令牌创建由于取消而完成的任务。

这些方法和属性的实现如下:

public async Task JoeAsync()
{
    await Task.CompletedTask;
}

public async Task JimAsync()
{
    await Task.FromException(new NullReferenceException("Fake null reference"));
}

// Make sure cancelToken.IsCancellationRequested == true
public async Task JoeAsync(CancellationToken cancellationToken)
{
    await Task.FromCanceled(cancellationToken);
}

public async Task<string> JanAsync()
{
    return await Task.FromResult("Should complete successfully");
}

public async Task<string> JedAsync()
{
    return await Task.FromException<string>(new NullReferenceException("Fake null reference"));
}

// Make sure cancelToken.IsCancellationRequested == true
public async Task<string> JanAsync(CancellationToken cancellationToken)
{
    return await Task.FromCanceled<string>(cancellationToken);
}
Run Code Online (Sandbox Code Playgroud)

测试上述方法的代码如下:

Task task;
var cancellationTokenSource = new CancellationTokenSource();
var cancelToken = cancellationTokenSource.Token;

cancellationTokenSource.Cancel();
task = this.JoeAsync();
Trace.Assert(task.IsCompleted);
Trace.Assert(task.IsCompletedSuccessfully);
task = this.JoeAsync(cancelToken);
Trace.Assert(task.IsCanceled);
Trace.Assert(cancelToken.IsCancellationRequested);
task = this.JimAsync();
Trace.Assert(task.IsFaulted);

Task<string> task2;

task2 = this.JanAsync();
Trace.Assert(task2.IsCompleted);
Trace.Assert(task2.IsCompletedSuccessfully);
task2 = this.JanAsync(cancelToken);
Trace.Assert(task2.IsCanceled);
Trace.Assert(cancelToken.IsCancellationRequested);
task2 = this.JedAsync();
Trace.Assert(task2.IsFaulted);
Run Code Online (Sandbox Code Playgroud)