go - 我如何告诉我的测试等待 goroutine 中的回调?

标签 go goroutine

我正在使用 dockerclient https://github.com/samalba/dockerclient它有一个基于 channel 的 API 来监听事件 client.MonitorEvents()和一个方便的回调方法client.StartMonitorEvents(callbackHandler) .

我想测试处理程序是否被调用。当然,dockerclient 在 goroutine 中处理事件。

现在,我的处理程序只是吐出一个日志。如果我在测试中等待,一切都会得到处理。如果我不这样做,它会在处理任何事情之前退出:

func eventCallback(event *dockerclient.Event, ec chan error, args ...interface{}) {
  log.Printf("Received event: %#v\n", *event)
}

我的测试看起来很简单:

func TestReceiveEvent(t *testing.T) {
   createAndMonitorEvents(server.URL)
   <- eventReady
   eventWriter.Write([]byte(someEvent))
   // test for something here
}

当然,除非我输入time.Sleep(),否则它不会工作。因为协程。

我如何告诉我的测试,“在运行测试之前等待其他例程完成它的工作”,而不是任意 sleep ?我希望测试我的处理程序是否正确处理了该事件。

备用接口(interface),client.MonitorEvents()返回一个 channel ,这给了我更大的控制权,但是从 channel 接收的东西会无限吐出 nil事件。

更新:

根据要求,createAndMonitorEvents 是:

func createAndMonitorEvents(url string) {
  // Init the client
  docker, _ := dockerclient.NewDockerClient(url, nil)

  // Listen to events
  stopchan := make(chan struct{})

  go func() {
    eventErrChan, err := docker.MonitorEvents(nil, stopchan)
    if err != nil {
        return
    }

    for e := range eventErrChan {
        if e.Error != nil {
            return
        }
        eventCallback(&e.Event, nil)
    }
    fmt.Println("monitor in place")
  }()
}

最佳答案

我想当你得到 nilMonitorEvents ,您只是看到事件 channel 已关闭( source of MonitorEvents 包含一个 close(eventOrErrorChan) ,支持这一点)。 evt, ok := <-c让您直接检查它是否( ok 关闭时为 false),以及 for evt := range c关闭后会停止。一般来说,从一个封闭的 channel 接收是specified到“[yield] 在收到任何先前发送的值后元素类型的零值”

关于等待回调的问题:回调可以关闭 channel 。 (或发送给它。)然后您的测试可以使用 select 等待指定的时间长度。 :

select {
case <-c:
        /* ...success... */
case <-time.After(5 * time.Second):
        /* timed out */
}

如果您知道某些错误情况会导致处理程序无法完成或无法运行,它可能会在不同的 channel 上发出这些情况的信号,或者通过向 c 发送不同的值来发出信号。 .

关于go - 我如何告诉我的测试等待 goroutine 中的回调?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31750100/

相关文章:

go - 如何反序列化 Kubernetes YAML 文件

mysql - 如何在gorm模型中传递动态表名

go - 从带有函数的 slice 中调用函数并获取返回值

http - Google App Engine Go 对慢速页面的 HTTP 请求

methods - 如何获取并发方法

Golang - 我可以有一个带有 slice 成员的结构吗?

go - 在 Go 中取消阻塞操作

go - 缓冲/非缓冲 channel 和死锁

go - 解决与 goroutines 的冲突?

concurrency - Go 如何决定何时在 goroutine 之间进行上下文切换?