使用 Nsubstitute 模拟 RestClient ExecuteAsync

Mocking RestClient ExecuteAsync using Nsubstitute

尝试使用 Nsubstitute 为 RestClient(来自 RestSharp)模拟 ExecuteAsync 方法时遇到了困难。我看过一个使用 Moq 的示例(此处:Mocking Restsharp executeasync method using moq),但我无法理解为什么以下代码使用 nsubstitute 失败:

RestClientMock.When(x => x.ExecuteAsync(Arg.Any<IRestRequest>(), Arg.Any<Action<IRestResponse>>()))
              .Do(x => new RestResponse { StatusCode = HttpStatusCode.NotFound });

我就是这样设置的,然后它会像这样命中要测试的代码:

 var tcs = new TaskCompletionSource<SendEmailResponse>();
_restClient.ExecuteAsync(_restRequest, (restResponse) => {

            if (restResponse.StatusCode != HttpStatusCode.OK)
               tcs.SetResult(new SendEmailResponse(ResponseType.Error, restResponse));

            else if (!_enableEmails)
                tcs.SetResult(new SendEmailResponse(ResponseType.EmailsTurnedOff, restResponse));

            else
                tcs.SetResult(new SendEmailResponse(ResponseType.Sent, restResponse));

        });

        return tcs.Task;

它似乎从未在模拟中执行我的回调代码,只是挂起,因为 tcs 从未设置。这里有人知道如何进行这项工作吗?

编辑:已解决。谢谢恩科西。所以我只是按照下面的解释更新它而不是返回。如果我更仔细地阅读文档,我会看到 David Tchepak 在评论中提到的部分。

ExecuteAsync 的函数签名是:

RestRequestAsyncHandle ExecuteAsync(IRestRequest request, Action<IRestResponse, RestRequestAsyncHandle> callback);

调用顺序:

RestClientMock.When(x => x.ExecuteAsync(Arg.Any<IRestRequest>(), Arg.Any<Action<IRestResponse>>()))
              .Do(x => new RestResponse { StatusCode = HttpStatusCode.NotFound });

你完全覆盖了原来的ExecuteAsync函数,使用回调的是调用函数的实现,但是你的替代实现根本没有使用回调!

我的建议是在 async 函数中使用 ExecuteTaskAsync

var restResponse = await _restClient.ExecuteTaskAsync(_restRequest);
if (restResponse.StatusCode != HttpStatusCode.OK)
    return new SendEmailResponse(ResponseType.Error, restResponse);

else if (!_enableEmails)
    return new SendEmailResponse(ResponseType.EmailsTurnedOff, restResponse);

else
    return new SendEmailResponse(ResponseType.Sent, restResponse);

之后,您应该可以模拟函数 ExecuteTaskAsync

从初步检查来看,您似乎没有对传递给模拟方法的回调操作做任何事情

RestClientMock
    .ExecuteAsync(
        Arg.Any<IRestRequest>(), 
        Arg.Do<Action<IRestResponse, RestRequestAsyncHandle>>(callback => 
            callback(new RestResponse { StatusCode = HttpStatusCode.NotFound}, null))
    )