C# 使用Nsubstitute模拟RestClient executesync

C# 使用Nsubstitute模拟RestClient executesync,c#,unit-testing,restsharp,nsubstitute,C#,Unit Testing,Restsharp,Nsubstitute,使用Nsubstitute从RestSharp模拟RestClient的ExecuteAsync方法一直很困难。我在这里看到了一个使用Moq的示例:但我始终无法理解以下代码使用nsubstitute失败的原因: RestClientMock.When(x => x.ExecuteAsync(Arg.Any<IRestRequest>(), Arg.Any<Action<IRestResponse>>())) .Do(x =&g

使用Nsubstitute从RestSharp模拟RestClient的ExecuteAsync方法一直很困难。我在这里看到了一个使用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的函数签名是:


之后,您应该能够模拟函数ExecuteTaskAsync。

ExecuteAAsync的函数签名是:


在这之后,您应该能够模拟函数ExecuteTaskAsync。

通过初始检查,您似乎没有对传入模拟方法的回调操作进行任何操作

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

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

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

从最初的检查来看,您似乎没有对传入模拟方法的回调操作执行任何操作。在.do调用中,您正在新建一个Response,但它没有在任何地方使用,因此将被忽略。根据@Nkosi的回答,您需要将该响应传递给回调。另请参见:,从初始检查来看,您似乎没有对传入模拟方法的回调操作执行任何操作。在.do调用中,您正在新建一个Response,但它没有在任何地方使用,因此将被忽略。根据@Nkosi的回答,您需要将该响应传递给回调。另请参见:,我使用的ExecuteAsync来自RestClientExtensions,定义为:public static restrequestAsynchHandle ExecuteAsynct此IRestClient客户端、IRestRequest请求、操作回调;我不确定是否可以在Moq中模拟扩展方法?不可能在Moq中模拟扩展方法你们都是对的。扩展方法不能在nsub中模拟。我将签名改为包含Restrequestasynchandle,它开始点击模拟,但正如Nkosi之前提到的,它所做的只是更新响应。在进一步阅读文档和上面的注释后,我能够解决问题。@Newbie:鉴于您希望公开基于任务的API,我建议使用RestClient的基于任务的API,而不是基于回调的API。我使用的ExecuteAsync来自RestClientExtensions,定义为:公共静态RestRequestAsynchHandle ExecuteAsync此IRestClient客户端、IRestRequest请求、动作回调;我不确定是否可以在Moq中模拟扩展方法?不可能在Moq中模拟扩展方法你们都是对的。扩展方法不能在nsub中模拟。我将签名改为包含Restrequestasynchandle,它开始点击模拟,但正如Nkosi之前提到的,它所做的只是更新响应。在进一步阅读文档和上面的注释后,我能够解决问题。@Newbie:鉴于您希望公开基于任务的API,我建议使用RestClient的基于任务的API,而不是基于回调的API。
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);
RestClientMock
    .ExecuteAsync(
        Arg.Any<IRestRequest>(), 
        Arg.Do<Action<IRestResponse, RestRequestAsyncHandle>>(callback => 
            callback(new RestResponse { StatusCode = HttpStatusCode.NotFound}, null))
    )