Ros*_*ane 5 testing unit-testing go
我正在用 Go 编写一个 JSON 验证器,我想测试另一个与我的验证器交互的对象。我已经将 Validator 实现为带有方法的结构。为了允许我将模拟 Validator 注入另一个对象,我添加了一个接口,该接口由 Validator 实现。然后我交换了参数类型以期待接口。
// Validator validates JSON documents.
type Validator interface {
// Validate validates a decoded JSON document.
Validate(doc interface{}) (valid bool, err error)
// ValidateString validates a JSON string.
ValidateString(doc string) (valid bool, err error)
}
// SchemaValidator is a JSON validator fixed with a given schema.
// This effectively allows us to partially apply the gojsonschema.Validate()
// function with the schema.
type SchemaValidator struct {
// This loader defines the schema to be used.
schemaLoader gojsonschema.JSONLoader
validationError error
}
// Validate validates the given document against the schema.
func (val *SchemaValidator) Validate(doc interface{}) (valid bool, err error) {
documentLoader := gojsonschema.NewGoLoader(doc)
return val.validate(documentLoader)
}
// ValidateString validates the given string document against the schema.
func (val *SchemaValidator) ValidateString(doc string) (valid bool, err error) {
documentLoader := gojsonschema.NewStringLoader(doc)
return val.validate(documentLoader)
}
Run Code Online (Sandbox Code Playgroud)
我的一个模拟看起来像这样:
// PassingValidator passes for everything.
type PassingValidator bool
// Validate passes. Always
func (val *PassingValidator) Validate(doc interface{}) (valid bool, err error) {
return true, nil
}
// ValidateString passes. Always
func (val *PassingValidator) ValidateString(doc string) (valid bool, err error) {
return true, nil
}
Run Code Online (Sandbox Code Playgroud)
这有效,但感觉不太对。协作者不会在生产代码中看到我的具体类型以外的任何东西;我只介绍了适合测试的界面。如果我在任何地方都这样做,我觉得我将通过为只有一个真正实现的方法编写接口来重复自己。
有一个更好的方法吗?
更新:我收回之前的回答。不要跨包导出接口。让您的函数返回具体类型,以便允许消费者创建自己的接口并根据需要进行覆盖。
请参阅: https: //github.com/golang/go/wiki/CodeReviewComments#interfaces HatTip:@rocketspacer
我通常还会在与包代码不同的包中编写测试代码。这样,我只能看到我导出的内容(如果导出太多,有时您会看到您弄乱的内容)。
遵循此指南,测试您的包的过程将是:
仅导出您的接口,而不导出您的具体类型。并添加一个New()构造函数,以便人们可以从您的包中实例化一个符合接口的默认实例。
package validator
type Validator interface {
Validate(doc interface{}) (valid bool, err error)
ValidateString(doc string) (valid bool, err error)
}
func New() Validator {
return &validator{}
}
type validator struct {
schemaLoader gojsonschema.JSONLoader
validationError error
}
func (v *validator) Validate(doc interface{}) (valid bool, err error) {
...
}
func (v *validator) ValidateString(doc string) (valid bool, err error) {
...
}
Run Code Online (Sandbox Code Playgroud)
这使您的 API 包保持干净,仅包含Validator并New()导出。
您的消费者只需要了解界面即可。
package main
import "foo.com/bar/validator"
func main() {
v := validator.New()
valid, err := v.Validate(...)
...
}
Run Code Online (Sandbox Code Playgroud)
这让您的消费者可以遵循依赖注入模式并New()在其使用之外实例化(调用 ),并在他们使用实例的地方注入实例。这将允许他们在测试中模拟接口并注入模拟。
或者,消费者可以不那么关心,只需编写上面的主要代码即可完成工作,该代码简短而有趣。
| 归档时间: |
|
| 查看次数: |
1744 次 |
| 最近记录: |