使用 C#(Client Library v3)对 Google Drive API 进行单元和集成测试?

Unit and Integration Testing for Google Drive API using C# (Client Library v3)?

我正在编写一个小型库,它使用 Google Drive API v3 C# 客户端库。 对我来说,这会带来很多痛苦,因为我不能为此目的使用 TDD 风格。

完成这项工作的常规方法如下所示:

internal async Task<Google.Apis.Drive.v3.Data.FileList> ReadFileList(string parentId, string pageToken, int pageSize)
{
    // Define parameters of request.
    var listRequest = this.driveService.Files.List();
    listRequest.PageSize = pageSize;
    listRequest.Q = "mimeType='application/vnd.google-apps.folder' and ('" + parentId + "' in parents)";
    listRequest.Fields = "nextPageToken, files(id, name)";
    listRequest.PageToken = pageToken;

    // List files.
    return await listRequest.ExecuteAsync();
}

对于单元测试,它包含几个依赖项(可能会使用工厂方法模式进行重构):

  1. 列表请求
  2. 文件列表

集成测试还有很多问题:

  1. 我应该如何验证此类服务?
  2. 即使经过身份验证,它也会污染真正的经过身份验证的驱动器帐户。
  3. 如何在其他人之间共享测试?
  4. 如果没有互联网连接,测试将无法通过。

Entity Framework Core 是否有类似 "In-Memory" 的提供程序? 如何使 Google 驱动单元和集成测试易于管理?

所以有了 Enterprise,您就走运了。

假设示例项目如下:

  1. 安装了一个 nuget 包 Google.Apis.Drive.v3
  2. 使用以下列表添加了 class:

这是实际的程序

 public class Class1
  {
    public async Task<Google.Apis.Drive.v3.Data.FileList> ReadFileList(string parentId, string pageToken, int pageSize)
    {
      // get the service somehow.
      var ds = new DriveService();

      var listRequest = ds.Files.List();
      listRequest.PageSize = pageSize;
      listRequest.Q = "mimeType='application/vnd.google-apps.folder' and ('" + parentId + "' in parents)";
      listRequest.Fields = "nextPageToken, files(id, name)";
      listRequest.PageToken = pageToken;

      // List files.
      return await listRequest.ExecuteAsync();
    }
  }

我们可以利用 Microsoft Fakes 框架的强大功能对此处的所有内容进行单元测试,而无需连接到互联网、google 驱动器、帐户等

  1. 添加 Microsoft 测试项目(注意:仅 dll 在这里不起作用)
  2. 在测试项目中,安装相同的nuget包。
  3. 为您的 classes 所在的库生成伪造程序集(在本例中,Google.Apis.Drive.v3Google.Apis,您使用的是来自两者的类型):

  4. 编写单元测试:

像这样

  [TestClass]
  public class UnitTest1
  {
    [TestMethod]
    public void TestMethod1()
    {
      using (Microsoft.QualityTools.Testing.Fakes.ShimsContext.Create())
      {
        int? usedPageSize = 0;
        var usedQ = string.Empty;
        var usedFields = string.Empty;
        var usedPageToken = string.Empty;

        Google.Apis.Drive.v3.Fakes.ShimFilesResource.ShimListRequest.AllInstances.PageSizeSetNullableOfInt32 =
          (request, i) => usedPageSize = i;
        Google.Apis.Drive.v3.Fakes.ShimFilesResource.ShimListRequest.AllInstances.QSetString = (request, s) => usedQ = s;
        Google.Apis.Drive.v3.Fakes.ShimDriveBaseServiceRequest<Google.Apis.Drive.v3.Data.FileList>.AllInstances
          .FieldsSetString = (request, s) => usedFields = s;

        Google.Apis.Drive.v3.Fakes.ShimFilesResource.ShimListRequest.AllInstances.PageTokenSetString = (request, s) => usedPageToken = s;
        Google.Apis.Requests.Fakes.ShimClientServiceRequest<Google.Apis.Drive.v3.Data.FileList>.AllInstances
            .ExecuteAsync =
          request =>
            Task.FromResult(
              new FileList
                {
                  ETag = "hello",
                  Files = new List<File> { new File { Name = "imafile" } },
                  IncompleteSearch = false,
                  Kind = "Somekind",
                  NextPageToken = null
                });

        Google.Apis.Drive.v3.Fakes.ShimFilesResource.AllInstances.List = resource => (FilesResource.ListRequest)FormatterServices.GetUninitializedObject(typeof(FilesResource.ListRequest));
        Google.Apis.Drive.v3.Fakes.ShimDriveService.Constructor = service => { }; // do not init the class
        Google.Apis.Drive.v3.Fakes.ShimDriveService.AllInstances.FilesGet = service => (FilesResource)FormatterServices.GetUninitializedObject(typeof(FilesResource));

        var target = new Class1();
        var result = target.ReadFileList("parent", "token", 42).Result;

        Assert.AreEqual(42, usedPageSize);
        Assert.AreEqual("mimeType='application/vnd.google-apps.folder' and ('parent' in parents)", usedQ);
        Assert.AreEqual("nextPageToken, files(id, name)", usedFields);
        Assert.AreEqual("token", usedPageToken);
        Assert.AreEqual(1, result.Files.Count);
        Assert.AreEqual("imafile", result.Files[0].Name);
        Assert.AreEqual("hello", result.ETag);
        Assert.IsFalse(result.IncompleteSearch.Value);
        Assert.AreEqual("Somekind", result.Kind);
        Assert.IsNull(result.NextPageToken);
      }
    }
  }