我正在使用 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")
}()
}
最佳答案
我想当你得到 nil
与 MonitorEvents
,您只是看到事件 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/