0%

在测试中验证服务契约

下面的测试mock掉了对CloudService服务的调用。这样的测试能够给我们信心,说:对该服务的调用是正常工作的吗?

1
2
3
4
5
6
7
8
9
10
11
@Test public void uploadFileToCloudStorage() {
when(mockCloudService.write(
WriteRequest.newBuilder().setUserId(“testuser”).setFileType(“plain/text”)...))
.thenReturn(WriteResponse.newBuilder().setUploadId(“uploadId”).build());

CloudUploader cloudUploader = new CloudUploader(mockCloudService);


Uri uri = cloudUploader.uploadFile(new File(“/path/to/foo.txt”));
// The uploaded file URI contains the user ID, file type, and upload ID. (Or does it?)
assertThat(uri).isEqualTo(new Uri(“/testuser/text/uploadId.txt”));

很多事情可能出错,尤其是当服务契约变得复杂时。例如,plain/text可能并不是一个有效值,同时也没有办法验证上传文件后生成的URI是正确的。
如果待测代码依赖该服务的契约,首选直接调用TA,而不是把这个调用mock掉。这可以给你给你更多自信,相信自己正确的使用了对应的服务:

1
2
3
4
5
@Test public void uploadFileToCloudStorage() {
CloudUploader cloudUploader = new CloudUploader(cloudService);
Uri uri = cloudUploader.uploadFile(”/path/to/foo.txt”);
assertThat(cloudService.retrieveFile(uri)).isEqualTo(readContent(“/path/to/foo.txt));
}

你可以如何调用这个服务呢?

  1. 使用一个Fake。一个fake是一个快速且轻量的实现,同时TA还表现的与真实服务一致。fake通常由服务的owner提供;不要创建你自己的fake,除非你可以保证fake的行为能够始终与真是实现保持一致。关于fake,参见:testing.googleblog.com/2013/06/testing-on-toilet-fake-your-way-to.html。
  2. 使用一个Hermetic server。这是一个在测试用例中拉起来的真实服务,并且与测试用例跑在同一台机器上。使用hermetic server的一个问题是,启动它以及与它交互会使测试执行变慢。关于hermetic servers,参考testing.googleblog.com/2012/10/hermetic-servers.html。

如果你依赖的服务没有fake或是hermetic server,mock就变成了你唯一的选择。但是如果你的测试用例没有真的验证服务调用契约,你必须使用额外的手段来保证服务调用是没问题的,比如通过一组详尽的end-to-end测试套件,或是依赖手工测试(这是很低效,且很难扩展的)。

翻译自

https://testing.googleblog.com/2018/11/testing-on-toilet-exercise-service-call.html