我尝试使用mgo.DialWithInfo
函数(在失败的情况下)对与MongoDB的连接进行单元测试。 mgo.DialWithInfo
不会返回错误,但会出现恐慌。
我试图添加恢复逻辑以从恐慌中恢复但没有成功。
我的问题是:
mgo.DialWithInfo
不会返回error
却会慌乱?代码:
功能
func Connect(mongoDBDialInfo *mgo.DialInfo) error {
log.Infof("connect to MongoDB with %v", mongoDBDialInfo)
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
mongoSession, err := mgo.DialWithInfo(mongoDBDialInfo)
if err != nil {
log.Errorf("error, cannot connect to MongoDB, %v", err)
msg := fmt.Sprintf("fail, cannot connect to MongoDB, %v", mongoDBDialInfo)
sf := "main.main"
errM := err.Error()
util.LogError(msg, sf, errM)
return err
}
DBSession = mongoSession
return err
}
单元测试
func TestConnect_Fail(t *testing.T) {
cf, err := config.GetConfigInstance()
if err != nil {
t.Errorf("expected, cannot connect to MongoDB but found, %v", err)
}
mongoDBDialInfo := &mgo.DialInfo{
Addrs: []string{cf.Config.MongoDB.Host + "ss"},
Timeout: time.Duration(cf.Config.MongoDB.Timeout) * time.Second,
Database: cf.Config.MongoDB.DBName,
Username: cf.Config.MongoDB.Username,
Password: cf.Config.MongoDB.Password,
}
err = Connect(mongoDBDialInfo)
if err == nil {
t.Errorf("expected, cannot connect to MongoDB but can")
}
}
答案 0 :(得分:5)
为什么
mgo.DialWithInfo
不会返回错误而是出现恐慌?
我不知道。可能是这样的:
或其组合。
尽管我不是mgo库的用户,但是您的代码看起来没有明显损坏,但这并不意味着您没有与外部资源进行通信的问题,这些问题无法通过查看代码来诊断。发布紧急消息的内容,这可能有助于我们准确确定问题所在。
为什么恢复不起作用?
目前尚不清楚您的问题,但从您的单元测试和this comment来看,恢复正在正常运行,但并非按预期运行,因为它不会返回错误恐慌的价值。
deferred语句中的recover()
调用将恢复对紧急恐慌例程的控制,返回在发生紧急情况时给出的值,并恢复正常的执行流程。 recover
会做的所有事情。除非您明确编写代码,否则它将不会对错误做任何事情。 (而且,出于完整性考虑,如果没有在调用堆栈的延迟函数中的某个位置调用recover
,恐慌最终会冒出来,对您的应用程序是致命的。)
在这种情况下,紧急情况有效:如果在执行Connect
函数期间发生紧急情况,应用程序不会致命退出。但是,您吃了恐慌却没有采取任何措施,也没有向呼叫者发出在Connect
方法期间发生错误的信号。
要报告此错误,您应该恢复恐慌并产生可以从Connect
函数返回的错误。您不能直接在deferred函数中返回值,但是可以使用命名返回值来返回。示例代码,跳过了函数主体的不必要部分:
func Connect(mongoDBDialInfo *mgo.DialInfo) (err error) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
// Return error from Connect with panic's value
err = fmt.Errorf("%v", r)
}
}()
// rest of function body
}