如何将Golang包测试数据文件分享给消费者?
How to share Golang package test data files with consumers?
我们创建了一个私有 go 库(实用程序包)以在服务之间共享通用 api 方法和业务逻辑。在实用程序包中,我们在“.json”文件中有数十个模拟 JSON 响应,用于模拟 api 测试。
使用此实用程序包的服务也希望访问相同的模拟文件,因为它们依赖相同的模拟 api 响应来测试各种内部业务逻辑。有没有一种方法可以通过一些相对文件路径或预编译它们(字节或字符串)来共享这些文件,以允许消费者测试通过标准 pkg 变量或引用相同的 .json 文件(文件路径或数据)方法,通过 go get github.com/whatever/utility-library
?
导入后
理想情况下,消费者测试可以通过子包(如“http/httptest”)访问这些文件,然后在自己的模拟服务器中引用内部 .json 文件(如httptest.GetBusinessObject.Response []byte
或 ResponseFilePath string
,等等)。我们希望继续将模拟响应存储在同一实用程序模块中的 .json 文件中,但只是将它们公开给消费者测试文件,严格用于测试目的。
my-api-pkg
├── go.mod
└── api
└── api.go
└── api_test.go // <= we currently access .json files here like utiltest.apiResponse []byte
└── apitest // <= sub pkg that contains testing methods and .json accessors
└── apitest.go
└── responses
└── api.response.json
my-service-pkg
├── go.mod
├── server.go
├── server_test.go
└── sub-pkg
└── subpkg.go
└── subpkg_test.go // <= want to access utiltest.apiResponse []byte for api mocks here
Non-Go 文件和 _test.go
文件不会编译成模块。要发布 _test.go
文件,请将它们重命名为 .go
文件并导出要向客户公开的变量和函数。
对于非 Go 文件,从 Go 1.16 开始,embed
它们:
package mycompany.com/common/testing
import _ "embed"
//go:embed responses/api.response.json
var MockApiJsonResponse []byte // or string
目录树如下所示:
testing
└── testing.go
└── responses
└── api.response.json
然后您的客户将能够像往常一样引用那些导出的变量和函数:
package mycompany.com/service
import (
"testing"
common_testing "mycompany.com/common/testing"
)
func TestThings(t *testing.T) {
mock := common_testing.MockApiJsonResponse
// ...
}
原答案!看来我的问题是我的 apitest
包中有一个导入的实用程序 fn,来自它自己的内部 testing.go 文件,这意味着它的 init() 函数是 运行 并污染了上游pkg 测试运行。
我最初的方法是合理的,但是 erptest pkg 不再被下载到上游服务 在我删除它的内部 testing.go 导入 之后。我更改了结构以像这样在根目录中引用测试目录,这恢复了 apitest pkg 的上游下载:
/my-api-pkg
├── go.mod
└── /api
└── api.go
└── api_test.go // <= we currently access .json files here like utiltest.apiResponse []byte
└── /apitest // <= sub pkg that contains testing methods and .json accessors
└── apitest.go
└── /testing // <= moving the files here re-enabled download and access or erptest code to upstream consumers
└── /files
└── /api.response.json
这是我的 apitest pkg 导出的基本结构,以允许通过 apitest.Domain().GetApiRoute1.Res1
访问上游文件(作为 []byte)
// accessor
type domainAccessor struct {
GetApiRoute1 getApiRoute1
...
}
func DomainAccessor() domainAccessor {
return domainAccessor{
GetApiRoute1: _GetApiRoute1,
...
}
}
// individual file accessors for each route
type getApiRoute1 struct {
Res1 []byte
Res2 []byte
}
var _GetApiRoute1 = getApiRoute1{
Res1: loadFile("testing/files/api/v1/domain/getApiRoute1.res.json"),
Res2: loadFile("testing/files/api/v1/domain/getApiRoute2.res.json"),
}
loadfile fn 读取文件到[]byte
func loadFile(filepath string) []byte {
dir := ""
_, filename, _, ok := runtime.Caller(0)
if ok {
dir = path.Join(path.Dir(filename), "..", "..", "..")
}
fullPath := path.Join(dir, filepath)
body, err := ioutil.ReadFile(fullPath)
if err != nil {
log.Println("Error apitest.loadFile: unable to read file", err)
panic(err)
}
return body
}
我们创建了一个私有 go 库(实用程序包)以在服务之间共享通用 api 方法和业务逻辑。在实用程序包中,我们在“.json”文件中有数十个模拟 JSON 响应,用于模拟 api 测试。
使用此实用程序包的服务也希望访问相同的模拟文件,因为它们依赖相同的模拟 api 响应来测试各种内部业务逻辑。有没有一种方法可以通过一些相对文件路径或预编译它们(字节或字符串)来共享这些文件,以允许消费者测试通过标准 pkg 变量或引用相同的 .json 文件(文件路径或数据)方法,通过 go get github.com/whatever/utility-library
?
理想情况下,消费者测试可以通过子包(如“http/httptest”)访问这些文件,然后在自己的模拟服务器中引用内部 .json 文件(如httptest.GetBusinessObject.Response []byte
或 ResponseFilePath string
,等等)。我们希望继续将模拟响应存储在同一实用程序模块中的 .json 文件中,但只是将它们公开给消费者测试文件,严格用于测试目的。
my-api-pkg
├── go.mod
└── api
└── api.go
└── api_test.go // <= we currently access .json files here like utiltest.apiResponse []byte
└── apitest // <= sub pkg that contains testing methods and .json accessors
└── apitest.go
└── responses
└── api.response.json
my-service-pkg
├── go.mod
├── server.go
├── server_test.go
└── sub-pkg
└── subpkg.go
└── subpkg_test.go // <= want to access utiltest.apiResponse []byte for api mocks here
Non-Go 文件和 _test.go
文件不会编译成模块。要发布 _test.go
文件,请将它们重命名为 .go
文件并导出要向客户公开的变量和函数。
对于非 Go 文件,从 Go 1.16 开始,embed
它们:
package mycompany.com/common/testing
import _ "embed"
//go:embed responses/api.response.json
var MockApiJsonResponse []byte // or string
目录树如下所示:
testing
└── testing.go
└── responses
└── api.response.json
然后您的客户将能够像往常一样引用那些导出的变量和函数:
package mycompany.com/service
import (
"testing"
common_testing "mycompany.com/common/testing"
)
func TestThings(t *testing.T) {
mock := common_testing.MockApiJsonResponse
// ...
}
原答案!看来我的问题是我的 apitest
包中有一个导入的实用程序 fn,来自它自己的内部 testing.go 文件,这意味着它的 init() 函数是 运行 并污染了上游pkg 测试运行。
我最初的方法是合理的,但是 erptest pkg 不再被下载到上游服务 在我删除它的内部 testing.go 导入 之后。我更改了结构以像这样在根目录中引用测试目录,这恢复了 apitest pkg 的上游下载:
/my-api-pkg
├── go.mod
└── /api
└── api.go
└── api_test.go // <= we currently access .json files here like utiltest.apiResponse []byte
└── /apitest // <= sub pkg that contains testing methods and .json accessors
└── apitest.go
└── /testing // <= moving the files here re-enabled download and access or erptest code to upstream consumers
└── /files
└── /api.response.json
这是我的 apitest pkg 导出的基本结构,以允许通过 apitest.Domain().GetApiRoute1.Res1
// accessor
type domainAccessor struct {
GetApiRoute1 getApiRoute1
...
}
func DomainAccessor() domainAccessor {
return domainAccessor{
GetApiRoute1: _GetApiRoute1,
...
}
}
// individual file accessors for each route
type getApiRoute1 struct {
Res1 []byte
Res2 []byte
}
var _GetApiRoute1 = getApiRoute1{
Res1: loadFile("testing/files/api/v1/domain/getApiRoute1.res.json"),
Res2: loadFile("testing/files/api/v1/domain/getApiRoute2.res.json"),
}
loadfile fn 读取文件到[]byte
func loadFile(filepath string) []byte {
dir := ""
_, filename, _, ok := runtime.Caller(0)
if ok {
dir = path.Join(path.Dir(filename), "..", "..", "..")
}
fullPath := path.Join(dir, filepath)
body, err := ioutil.ReadFile(fullPath)
if err != nil {
log.Println("Error apitest.loadFile: unable to read file", err)
panic(err)
}
return body
}