unit-testing - 测试接受在 Golang 中不返回值的回调函数的方法
问题描述
我正在尝试测试以下功能:
// SendRequestAsync sends request asynchronously, accepts callback
// func, which it invokes
//
// Parameters:
// - `context` : some context
// - `token` : some token
// - `apiURL` : the URL to hit
// - `callType` : the type of request to make. This should be one of
// the HTTP verbs (`"GET"`, `"POST"`, `"PUT"`, `"DELETE"`, ...)
// - `callBack` : the func to invoke upon completion
// - `callBackCustomData`: the data to invoke `callBack` with
//
// Since this is an async request, it doesn't return anything.
func (a *APICoreSt) SendRequestAsync(context interface{}, token string, apiURL string, callType APIType, header map[string]string, jsonBody []byte,
callBack OnCompletion, callBackCustomData interface{}) {
go func(data interface{}) {
callBack(a.SendRequest(context, token, apiURL, callType, header, jsonBody), data)
}(callBackCustomData)
}
其中OnCompletion
定义为:
type OnCompletion func(result CallResultSt, data interface{})
我的头脑立即想到创建一个间谍回调。为此,我分叉了这个框架,提出了以下内容:
// outside the test function
type MySpy struct {
*spies.Spy
}
func (my *MySpy) Callback(res CallResultSt, data interface{}) {
my.Called(res, data)
fmt.Println("Hello world")
return
}
//in the test function
spy := new(MySpy)
//...some table-driven test logic the generator came up with, containing my data
spy.MatchMethod("Callback", spies.AnyArgs)
assert.NotEmpty(t, spies.CallsTo("Callback"))
它向我打招呼
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
我该如何解决这个问题,并测试这个方法?
解决方案
我会抛弃间谍的东西。这个任务很简单,你不需要外部依赖来处理它。相反,您可以制作自己的“间谍”,该“间谍”具有在调用函数时将 args 传递到的通道。在您的测试中,您然后尝试从通道接收。这将强制测试等待回调函数被调用。您还可以考虑添加一个超时时间,以便测试可以失败,而不是在函数从未被调用时永远阻塞。
// outside the test function
type MySpy struct {
Args chan MySpyArgs
}
type MySpyArgs struct {
Res CallResultSt
Data interface{}
}
func (my *MySpy) Callback(res CallResultSt, data interface{}) {
my.Args <- MySpyArgs{Res: res, Data: data}
}
//in the test function
spyChan := make(chan MySpyArgs)
spy := &MySpy{spyChan}
//...some table-driven test logic the generator came up with, containing my data
args := <-spyChan
// can now assert arguments were as you expected, etc.
一个粗略的工作示例: https: //play.golang.org/p/zUYpjXdkz-4。
如果你想使用超时:
...
select {
case args := <-spyChan:
// assertions on args
case <-time.After(5 * time.Second):
// prevent blocking for over 5 seconds and probably fail the test
}
推荐阅读
- angular - 如何更新文件输入字段的值
- django - 运行 WSGI 应用程序时出错,ImportError: No module named 'mysite' during hosting on pythonanywhere
- charts - 谷歌表格数组 - 填补不规则数据的空白
- git - 将 git 日志日期格式保存在 .gitconfig 中
- python - ConnectionResetError:[Errno 104] 对等 python 3 重置连接
- android - 在Android上编辑表格JS Tablulator时键盘闪烁
- azure - 如何在 Azure Function 应用程序上安装根证书和中间证书
- python - 如何根据行/列名称将数据框数组对角线下的值添加到更大的数组中?
- angular - 如何将 Angular 应用程序部署到客户端 URL
- ionic-framework - 如何在 Ionic 3 中使用 PayPal 修复“对象(...)不是函数错误”