用例 – BookSwap应用的边界情况
本章教会了我们两种新的测试技术:模糊测试和基于属性的测试。我们已经学习了如何将这些技术应用于一个简单的函数,该函数提供了返回输入映射中包含的按键排序值的功能。在本节中,我们将通过讨论如何将这些技术应用于我们迄今为止构建的 BookSwap 应用程序来结束我们的探索。
如前所述,健壮的代码应该测试任何不是它自己生成的变量。我们将这些输入命名为来自不受信任的来源。图10.4 展示了从处理服务的角度来看可以被视为不受信任的所有输入:

我们在 BookSwap 的服务中识别出两个不受信任的输入来源:
-
UserService 从用户接收输入。由于我们无法控制用户提交的内容,因此这种交互是不受信任输入的来源。
-
UserService 从 BookService 接收信息。正如您可能从我们在第8章《测试微服务架构》中的讨论中记得的那样,微服务在没有任何中央监督的情况下发生变化。因此,由于
UserService
无法控制此外部服务提供的功能,因此这种交互是不受信任输入的来源。 -
同样适用于 BookService,它从 UserService 接收请求。虽然这种交互不会主动向
BookService
发送输入,但请求仍然包含不受信任的信息。
基于这些见解,我们可以识别出需要为我们 Web 应用程序公开的 HTTP 处理程序实现模糊测试的需求。我们将测试我们在前几章中也测试过的用户创建操作。使用 Go 的模糊测试功能可以轻松实现 HTTP 端点的模糊测试:
func FuzzTestUserCreation(f *testing.F) {
// 其他初始化
f.Add("test user", "1 London Road", "N1", "UK")
f.Fuzz(func(t *testing.T, name string, address string, postCode string, country string) {
requestBody, err := json.Marshal(map[string]string{
"name": name,
"address": address,
"post_code": postCode,
"country": country,
})
require.Nil(t, err)
req := bytes.NewBuffer(requestBody)
resp, err := http.Post(userEndpoint, "application/json", req)
assert.Nil(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Nil(t, err)
assert.NotNil(t, resp)
})
}
除了与模糊测试工具的交互以设置模糊目标和参数外,此测试的主体与我们已经熟悉的 HTTP 测试相同。我们为用户创建请求所需的字段添加了四个模糊参数。在模糊目标内部,我们创建并将请求编组为 JSON 格式。最后,我们使用 http.Post
函数将请求发送到 /users
端点。正如我们在本章中看到的之前的模糊测试示例一样,我们使用 LONG=true go test -fuzz FuzzTestUserCreation -fuzztime=5s ./chapter10 -v
命令运行此测试。它需要 BookSwap 应用程序启动并运行,我们可以使用我们迄今为止看到的 Docker 命令轻松完成此操作:docker compose -f docker-compose.book-swap.chapter10.yml up --build
。测试还依赖于环境变量来构建被测 URL。如果要使用默认值运行,请将 BOOKSWAP_BASE_URL
环境变量设置为 http://localhost
,并将 BOOKSWAP_PORT
环境变量设置为 3000 到您的终端会话。
这结束了我们对模糊测试和基于属性的测试的探索,这是两种相关的技术,使我们能够轻松编写涵盖各种边缘情况的测试策略。这两种技术都与 Go 的测试包很好地集成,并且可以在我们应用程序测试的任何级别轻松实现。