Go 1.11 已达到支持终止期限,将于 2026 年 1 月 31 日
弃用。弃用后,您将无法部署 Go 1.11 应用,即使您的组织之前曾使用组织政策重新启用旧版运行时的部署也是如此。现有的 Go 1.11 应用在
弃用日期之后将继续运行并接收流量。我们建议您
迁移到最新支持的 Go 版本。
Go 本地单元测试
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
本地单元测试在您的环境内部运行,而无需访问远程组件。
App Engine 提供的测试实用程序使用在本地实现的 Cloud Datastore 及其他 App Engine 服务。
开发服务在本地模拟实际服务的行为,以进行测试。例如,您可以按照编写 Cloud Datastore 和 Memcache 测试中显示的数据存储区用法,对数据存储区代码进行测试,而无需向实际数据存储区发送任何请求。在数据存储区单元测试过程中存储的任何实体均会在本地存储,并会在测试运行之后删除。您无需依赖数据存储区本身便可快速运行小型测试。
本文档介绍了如何使用 Go 测试软件包针对本地 App Engine 服务编写单元测试。
Go 测试软件包
您可以使用 goapp
工具自动下载、构建、测试 Go 软件包。goapp
是 Go 版 App Engine SDK 的一部分。
您可以结合使用 goapp test
命令与标准 Go testing
软件包,针对您的应用代码运行单元测试。如需了解对 Go 进行测试的背景信息,请参阅如何编写 Go 代码的“测试”部分和测试软件包参考文档。
单元测试包含在以后缀 _test.go
结尾的文件中。例如,假设您要对一个名为 composeNewsletter
的函数进行测试,该函数返回 *mail.Message
。以下 newsletter_test.go
文件显示了适用于该函数的简单测试:
您可以使用 goapp test
命令从软件包的目录中调用该测试:
goapp test
goapp
工具位于 App Engine SDK 的根目录中,我们建议将该目录置于您系统的 PATH
变量中,以便更轻松地运行测试。
aetest
软件包
许多对 App Engine 服务的函数调用都要求将 context.Context
作为参数。您可以使用 SDK 提供的 appengine/aetest
软件包创建虚假 context.Context
,以便使用开发环境中提供的服务运行测试。
调用 aetest.NewContext
时,系统会在子进程中启动 dev_appserver.py
,此操作将用于在测试期间处理 API 调用。您可以调用 done
来关闭该子进程。
为了更好地控制底层实例,您可以改为使用 aetest.NewInstance
。这样您便能够创建多个上下文,并将这些上下文与 http.Request
对象相关联。
如需了解详情,请参阅 aetest 软件包参考。
编写 Cloud Datastore 和 Memcache 测试
使用 aetest
软件包创建 context.Context
后,您可以轻松测试使用数据存储区或 Memcache 的代码:在您的测试中,调用 aetest.NewContext
来创建上下文,以传递给测试中的函数。
SDK 中的 transaction
演示应用提供示例,说明如何构建代码以实现可测试性,以及如何对使用数据存储区的代码进行测试:
您可以使用 goapp test
命令运行此测试:
goapp test ./demos/transaction
Memcache 测试遵循同样的模式:在您的测试中设置 Memcache 的初始状态,运行正在接受测试的函数,并验证该函数是否以您预期的方式查询/修改了 Memcache。
如未另行说明,那么本页面中的内容已根据知识共享署名 4.0 许可获得了许可,并且代码示例已根据 Apache 2.0 许可获得了许可。有关详情,请参阅 Google 开发者网站政策。Java 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-09-04。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["很难理解","hardToUnderstand","thumb-down"],["信息或示例代码不正确","incorrectInformationOrSampleCode","thumb-down"],["没有我需要的信息/示例","missingTheInformationSamplesINeed","thumb-down"],["翻译问题","translationIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-09-04。"],[[["\u003cp\u003eLocal unit tests can be run within your environment without the need to access remote components, using local implementations of App Engine services like Cloud Datastore.\u003c/p\u003e\n"],["\u003cp\u003eThe \u003ccode\u003egoapp test\u003c/code\u003e command, in combination with the standard Go \u003ccode\u003etesting\u003c/code\u003e package, facilitates running unit tests against your application code, which are contained in files ending with the suffix \u003ccode\u003e_test.go\u003c/code\u003e.\u003c/p\u003e\n"],["\u003cp\u003eThe \u003ccode\u003eaetest\u003c/code\u003e package within the App Engine SDK enables the creation of a fake \u003ccode\u003econtext.Context\u003c/code\u003e for testing code that interacts with App Engine services in the development environment.\u003c/p\u003e\n"],["\u003cp\u003eTesting code that utilizes the datastore or memcache is streamlined by creating a \u003ccode\u003econtext.Context\u003c/code\u003e using \u003ccode\u003eaetest.NewContext\u003c/code\u003e within the test, allowing you to pass it to the function being tested.\u003c/p\u003e\n"],["\u003cp\u003e\u003ccode\u003eaetest.NewInstance\u003c/code\u003e provides more control over the underlying test instance, enabling the creation of multiple contexts and their association with \u003ccode\u003ehttp.Request\u003c/code\u003e objects.\u003c/p\u003e\n"]]],[],null,["# Local Unit Testing for Go\n\nLocal unit tests run inside your environment without accessing remote components.\nApp Engine provides testing utilities that use local implementations of Cloud\nDatastore and other [App Engine services](/appengine/docs/legacy/standard/go111/apis).\n\nThe development services simulate the behaviour of the real service locally for\ntesting. For example, the datastore usage shown in [Writing Cloud Datastore\nand Memcache Tests](#Go_Writing_Datastore_and_memcache_tests) allows you to test\nyour datastore code without making any requests to the real datastore. Any\nentity stored during a datastore unit test is stored locally and is deleted\nafter the test run. You can run small, fast tests without any dependency on the\ndatastore itself.\n\nThis document describes how to write unit tests against local App Engine\nservices using the Go testing package.\n\nThe Go Testing package\n----------------------\n\nYou can automate the downloading, building, and testing of Go packages by using\nthe `goapp` tool. `goapp` is part of the\n[App Engine SDK for Go](/appengine/docs/legacy/standard/go111/download#appengine_sdk).\n\nThe combination of the `goapp test` command and the standard Go\n`testing` package can be used to run unit tests against your application code.\nFor a background on testing with Go, see the Testing section of [How to Write\nGo Code](http://golang.org/doc/code.html#Testing) and the [testing package\nreference](http://golang.org/pkg/testing/).\n\nUnit tests are contained in files ending with the suffix `_test.go`. For\nexample, suppose you want to test a function named `composeNewsletter` which\nreturns a `*mail.Message`. The following `newsletter_test.go` file shows\na simple test for that function: \n\n package newsletter\n\n import (\n \t\"reflect\"\n \t\"testing\"\n\n \t\"google.golang.org/appengine/mail\"\n )\n\n func TestComposeNewsletter(t *testing.T) {\n \twant := &mail.https://cloud.google.com/appengine/docs/legacy/standard/go111/reference/latest/mail.html#google_golang_org_appengine_mail_Message{\n \t\tSender: \"newsletter@appspot.com\",\n \t\tTo: []string{\"User \u003cuser@example.com\u003e\"},\n \t\tSubject: \"Weekly App Engine Update\",\n \t\tBody: \"Don't forget to test your code!\",\n \t}\n \tif msg := composeNewsletter(); !reflect.DeepEqual(msg, want) {\n \t\tt.Errorf(\"composeMessage() = %+v, want %+v\", msg, want)\n \t}\n }\n\nThis test would be invoked using the `goapp test` command from within the\npackage's directory: \n\n```\ngoapp test\n```\n\nThe `goapp` tool is found in the root directory of the App Engine SDK. We\nrecommend putting this directory in your system's `PATH` variable to make\nrunning tests simpler.\n\nThe `aetest` package\n--------------------\n\nMany function calls to App Engine services require a `context.Context`\nas an argument. The `appengine/aetest` package provided with the SDK\nallows you to create a fake `context.Context` to run your tests using the\nservices provided in the development environment. \n\n import (\n \t\"testing\"\n\n \t\"google.golang.org/appengine/aetest\"\n )\n\n func TestWithContext(t *testing.T) {\n \tctx, done, err := aetest.https://cloud.google.com/appengine/docs/legacy/standard/go111/reference/latest/aetest.html#google_golang_org_appengine_aetest_NewContext()\n \tif err != nil {\n \t\tt.Fatal(err)\n \t}\n \tdefer done()\n\n \t// Run code and tests requiring the context.Context using ctx.\n \t// ...\n }\n\nThe call to `aetest.NewContext` will start `dev_appserver.py` in a subprocess,\nwhich will be used to service API calls during the test. This subprocess will be\nshutdown with the call to `done`.\n\nFor more control over the underlying instance, you can use `aetest.NewInstance`\ninstead. This gives you the ability to create multiple contexts, and to\nassociate those with `http.Request` objects. \n\n import (\n \t\"errors\"\n \t\"testing\"\n\n \t\"golang.org/x/net/context\"\n\n \t\"google.golang.org/appengine\"\n \t\"google.golang.org/appengine/aetest\"\n \t\"google.golang.org/appengine/datastore\"\n )\n\n func TestMyFunction(t *testing.T) {\n \tinst, err := aetest.NewInstance(nil)\n \tif err != nil {\n \t\tt.Fatalf(\"Failed to create instance: %v\", err)\n \t}\n \tdefer inst.Close()\n\n \treq1, err := inst.NewRequest(\"GET\", \"/gophers\", nil)\n \tif err != nil {\n \t\tt.Fatalf(\"Failed to create req1: %v\", err)\n \t}\n \tc1 := appengine.NewContext(req1)\n\n \treq2, err := inst.NewRequest(\"GET\", \"/herons\", nil)\n \tif err != nil {\n \t\tt.Fatalf(\"Failed to create req2: %v\", err)\n \t}\n \tc2 := appengine.NewContext(req2)\n\n \t// Run code and tests with *http.Request req1 and req2,\n \t// and context.Context c1 and c2.\n \t// ...\n }\n\nRead the [aetest package\nreference](/appengine/docs/legacy/standard/go111/tools/localunittesting/reference)\nfor more information.\n\nWriting Cloud Datastore and\nmemcache tests\n------------------------------------------\n\nTesting code which uses the datastore or memcache is simple once you create a\n`context.Context` with the `aetest` package: in your test call\n`aetest.NewContext` to create a context to pass to the function under test.\n\nThe `transaction` demo application in the SDK has an example of structuring the\ncode to allow testability, and how to test code which uses the datastore: \n\n func TestWithdrawLowBal(t *testing.T) {\n \tctx, done, err := aetest.NewContext()\n \tif err != nil {\n \t\tt.Fatal(err)\n \t}\n \tdefer done()\n \tkey := datastore.NewKey(ctx, \"BankAccount\", \"\", 1, nil)\n \tif _, err := datastore.Put(ctx, key, &BankAccount{100}); err != nil {\n \t\tt.Fatal(err)\n \t}\n\n \terr = withdraw(ctx, \"myid\", 128, 0)\n \tif err == nil || err.Error() != \"insufficient funds\" {\n \t\tt.Errorf(\"Error: %v; want insufficient funds error\", err)\n \t}\n\n \tb := BankAccount{}\n \tif err := datastore.Get(ctx, key, &b); err != nil {\n \t\tt.Fatal(err)\n \t}\n \tif bal, want := b.Balance, 100; bal != want {\n \t\tt.Errorf(\"Balance %d, want %d\", bal, want)\n \t}\n }\n\nThis test can be run using the `goapp test` command: \n\n```\ngoapp test ./demos/transaction\n```\n\nTests for memcache follow the same pattern: set up the initial state of the\nmemcache in your test, run the function being tested, and verify the function\nhas queried/modified the memcache in the way you expect."]]