2018-08-16 15:44
浏览 279


I'm trying to test the following function:

// 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)

where OnCompletion is defined by:

type OnCompletion func(result CallResultSt, data interface{})

My mind instantly thinks to create a spy callback. To do so, I forked this framework, came up with the following:

// outside the test function
type MySpy struct {

func (my *MySpy) Callback(res CallResultSt, data interface{}) {
    my.Called(res, data)
    fmt.Println("Hello world")

//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"))

and it greeted me with

panic: runtime error: invalid memory address or nil pointer dereference [recovered]
    panic: runtime error: invalid memory address or nil pointer dereference

How do I remedy this, and test this method?

图片转代码服务由CSDN问答提供 功能建议


   // SendRequestAsync异步发送请求,接受回调
 // func,由它调用
 //-`callType`:发出请求的类型。 这应该是
 // HTTP动词之一(“ GET”,“ POST”,“ PUT”,“ DELETE”,...)
 //-`callBack`: 完成时要调用的函数
func(a *  APICoreSt)SendRequestAsync(上下文接口{},令牌字符串,apiURL字符串,callType APIType,标头映射[string]字符串,jsonBody [] byte,
 callBack OnCompletion,callBackCustomData接口{}){
 go func(数据接口{}  ){

其中 OnCompletion 的定义如下:

  type OnCompletion func(结果CallResultSt,数据接口{})

我的大脑立即想到创建一个间谍回调。 为此,我分叉了此框架,提出了以下建议:

type MySpy struct {
 * spies.Spy 
func(我的* MySpy)回调(res CallResultSt,数据接口{})  {
 fmt.Println(“ H​​ello world”)
spy:= new(MySpy)
  // ...生成器提出了一些表驱动测试逻辑,其中包含我的数据
spy.MatchMethod(“ Callback”,spies.AnyArgs)
assert.NotEmpty(t,spies.CallsTo(“ Callback”)  )


  panic向我打招呼:运行时错误:无效的内存地址或nil指针取消引用[ 已恢复] 


  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • duannuo7878 2018-08-16 21:23

    I would ditch the spy stuff. This task is simple enough that you shouldn't need an external dependency to handle it. You could instead make your own "spy" that has a channel it passes args into when the function is called. In your test, you then attempt to receive from the channel. That will force the test to wait for the callback function to be called. You may also consider adding a timeout period so that the test can fail instead of blocking forever if the function is never called.

    // 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.

    A crude working example:

    And if you want to use a timeout:

    select {
    case args := <-spyChan:
        // assertions on args
    case <-time.After(5 * time.Second):
        // prevent blocking for over 5 seconds and probably fail the test
    解决 无用
    打赏 举报

相关推荐 更多相似问题