如果您使用Dargo 注入框架,您可以绑定更高等级的接口或结构版本,然后将其用于您的代码中,而不是您的普通代码绑定的东西。
假设您在普通代码中定义了一些这样的服务:
var globalLocator ioc.ServiceLocator
type AnExpensiveService interface {
DoExpensiveThing(string) (string, error)
}
type NormalExpensiveServiceData struct {
}
func (nesd *NormalExpensiveServiceData) DoExpensiveThing(thingToDo string) (string, error) {
time.Sleep(5 * time.Second)
return "Normal", nil
}
type SomeOtherServiceData struct {
ExpensiveService AnExpensiveService `inject:"AnExpensiveService"`
}
func init() {
myLocator, err := ioc.CreateAndBind("TestingExampleLocator", func(binder ioc.Binder) error {
binder.Bind("UserService", SomeOtherServiceData{})
binder.Bind("AnExpensiveService", NormalExpensiveServiceData{})
return nil
})
if err != nil {
panic(err)
}
globalLocator = myLocator
}
func DoSomeUserCode() (string, error) {
raw, err := globalLocator.GetDService("UserService")
if err != nil {
return "", err
}
userService, ok := raw.(*SomeOtherServiceData)
if !ok {
return "", fmt.Errorf("Unkonwn type")
}
return userService.ExpensiveService.DoExpensiveThing("foo")
}
现在您不想在测试代码中调用昂贵的服务。在下面的测试代码中,昂贵的服务被替换为模拟服务,具有更高的等级。当测试调用用户代码时,将使用模拟代替普通的昂贵代码。下面是测试代码:
type MockExpensiveService struct {
}
func (mock *MockExpensiveService) DoExpensiveThing(thingToDo string) (string, error) {
return "Mock", nil
}
func putMocksIn() error {
return ioc.BindIntoLocator(globalLocator, func(binder ioc.Binder) error {
binder.Bind("AnExpensiveService", MockExpensiveService{}).Ranked(1)
return nil
})
}
func TestWithAMock(t *testing.T) {
err := putMocksIn()
if err != nil {
t.Error(err.Error())
return
}
result, err := DoSomeUserCode()
if err != nil {
t.Error(err.Error())
return
}
if result != "Mock" {
t.Errorf("Was expecting mock service but got %s", result)
return
}
}
当调用 DoUserCode 时,会查找 UserService,而不是获取正常的实现,而是注入模拟。
之后,测试只是验证注入的是模拟而不是正常代码。
这就是使用 Dargo 进行单元测试的基础知识!希望对你有帮助