模拟和单元测试 graphql-dotnet

Mocking and unit testing graphql-dotnet

提问人:Dawid Rutkowski 提问时间:11/8/2023 更新时间:11/8/2023 访问量:84

问:

我正在使用 graphql-dotnet 库从我的 C# 代码中查询一些 GraphQL API。有没有办法轻松模拟单元测试?GraphQLHttpClient

C# 单元测试 最小起订量 graphql-dotnet

评论

0赞 MakePeaceGreatAgain 11/8/2023
你自己尝试了什么?
0赞 Dawid Rutkowski 11/8/2023
通过直接模拟 GraphQLHttpClient 或传递 HttpClient 的模拟版本来@MakePeaceGreatAgain多种方法。我最终得到了一个解决方案,我在下面的答案中描述了该解决方案(我认为这可能对其他用户有所帮助)。

答:

0赞 Dawid Rutkowski 11/8/2023 #1

直接模拟并不容易,但您可以在其中一个构造函数中提供自己的构造函数并模拟 .请看下面的代码:GraphQLHttpClientHttpClientGraphQLHttpClientHttpMessageHandler

HttpContent content = new StringContent(_responseContent, Encoding.UTF8, "application/json");
var response = new HttpResponseMessage
{
    StatusCode = HttpStatusCode.OK,
    Content = content
};

var httpMessageHandler = new Mock<HttpMessageHandler>();
httpMessageHandler.Protected()
                  .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
                  .ReturnsAsync(response);

HttpClient client = new HttpClient(httpMessageHandler.Object);

GraphQLHttpClient graphQlClient = new GraphQLHttpClient(GetOptions(), new NewtonsoftJsonSerializer(), client);

上面的代码工作正常,并允许我在变量中提供我想要的真正 GQL API 的任何测试 JSON 输出。 第一行和两个参数 - - 非常重要。如果不提供内容类型,GraphQLHttpClient 将因此行而引发异常。我花了一段时间才找到它。_responseContentEncoding.UTF8, "application/json"

我正在使用库来模拟对象。Moq

评论

1赞 Michał Turczyn 11/8/2023
因此,这似乎归结为嘲笑旧的 HttpMessageHandler,就像所有使用硬编码 depndency 的解决方案一样HttpClient
0赞 AK94 11/8/2023 #2

实现扩展了 .介绍了以下方法:GraphQLHttpClientIGraphQLWebSocketClientIGraphQLClientIGraphQLClient

Task<GraphQLResponse<TResponse>> SendQueryAsync<TResponse>(GraphQLRequest request, CancellationToken cancellationToken = default);
        
Task<GraphQLResponse<TResponse>> SendMutationAsync<TResponse>(GraphQLRequest request, CancellationToken cancellationToken = default);

然后,在测试代码中,您可以为 .您只需要知道您正在将依赖注入与提供的接口结合使用。IGraphQLClient

它可能看起来像这样:

public class UnitTest1
{
   [Fact]
   public void Test1()
   {
      var mockedService = new Mock<IGraphQLClient>();
      mockedService
         Setup(ms => ms.SendQueryAsync<string>(It.IsAny<GraphQLRequest>(), It.IsAny<CancellationToken>()))
         .ReturnsAsync(new GraphQLResponse<string>());

         var service = new AnythingWithGraphQLDependency(mockedService.Object);

   }
}

public class AnythingWithGraphQLDependency
{
   private readonly IGraphQLClient _client;

   public AnythingWithGraphQLDependency(IGraphQLClient client)
   {
      _client = client;
   }

   public async Task<string> Test(string query, CancellationToken cancellationToken)
   {
      var response = await _client.SendQueryAsync<string>(new GraphQLRequest(query), cancellationToken);

      //Code to be tested goes here
   }
}