我如何告诉我的测试等待 goroutine 中的回调?
How do I tell my test to wait for a callback in a goroutine?
我正在使用 dockerclient https://github.com/samalba/dockerclient,它有一个基于通道的 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
}
当然,除非我因为 goroutine 放入一个 time.Sleep()
,否则它不会工作。
我如何告诉我的测试,"wait for the other routine to do its work before running the test",而不是任意睡眠?我希望测试我的处理程序是否正确处理了该事件。
备用接口,client.MonitorEvents()
returns 一个通道,它给了我更大的控制权,但是从通道接收会吐出无限的 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")
}()
}
我认为当您使用 MonitorEvents
获得 nil
s 时,您只是看到事件通道已关闭(source of MonitorEvents
includes a close(eventOrErrorChan)
, supporting this). evt, ok := <-c
lets you directly check if that (ok
will be false when it's closed), and for evt := range c
will stop after it's closed. In general, receiving from a closed channel is specified 到“[yield] 元素类型为零收到任何先前发送的值后的值
关于等待回调的问题:回调可以关闭通道。 (或发送给它。)然后你的测试可以等待指定的时间长度 select
:
select {
case <-c:
/* ...success... */
case <-time.After(5 * time.Second):
/* timed out */
}
如果您知道某些错误情况会导致处理程序无法完成或无法完成 运行,它可能会在不同的通道上发出这些情况的信号,或者通过向 c
发送不同的值。
"How do I tell my test, "等待其他程序在 运行 测试之前完成它的工作”,而不是任意睡眠?”
您要么在频道上发送,要么关闭频道。调用者正在接收执行块,直到出现信号。我真的不知道如何将您的代码工作成有意义的东西......你不能在函数中分配停止通道,你必须将它传递给函数以便调用者可以监听它。就像这甚至如何编译?
func TestReceiveEvent(t *testing.T) {
createAndMonitorEvents(server.URL)
<- eventReady // undeclared variable, and discarding the event you recieved?
eventWriter.Write([]byte(someEvent)) //and another variable that is not declared
// test for something here
}
也许可以帮助您入门...
func createAndMonitorEvents(url string, done chan bool) {
//the codes
close(done)
}
func TestReceiveEvent(t *testing.T) {
eventReady := make(chan bool)
createAndMonitorEvents(server.URL, eventReady)
<- eventReady
eventWriter.Write([]byte(someEvent)) // dis still don't exist though
// test for something here
}
我认为这可以帮助
A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. Then each of the goroutines runs and calls Done when finished. At the same time, Wait can be used to block until all goroutines have finished.
我正在使用 dockerclient https://github.com/samalba/dockerclient,它有一个基于通道的 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
}
当然,除非我因为 goroutine 放入一个 time.Sleep()
,否则它不会工作。
我如何告诉我的测试,"wait for the other routine to do its work before running the test",而不是任意睡眠?我希望测试我的处理程序是否正确处理了该事件。
备用接口,client.MonitorEvents()
returns 一个通道,它给了我更大的控制权,但是从通道接收会吐出无限的 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")
}()
}
我认为当您使用 MonitorEvents
获得 nil
s 时,您只是看到事件通道已关闭(source of MonitorEvents
includes a close(eventOrErrorChan)
, supporting this). evt, ok := <-c
lets you directly check if that (ok
will be false when it's closed), and for evt := range c
will stop after it's closed. In general, receiving from a closed channel is specified 到“[yield] 元素类型为零收到任何先前发送的值后的值
关于等待回调的问题:回调可以关闭通道。 (或发送给它。)然后你的测试可以等待指定的时间长度 select
:
select {
case <-c:
/* ...success... */
case <-time.After(5 * time.Second):
/* timed out */
}
如果您知道某些错误情况会导致处理程序无法完成或无法完成 运行,它可能会在不同的通道上发出这些情况的信号,或者通过向 c
发送不同的值。
"How do I tell my test, "等待其他程序在 运行 测试之前完成它的工作”,而不是任意睡眠?”
您要么在频道上发送,要么关闭频道。调用者正在接收执行块,直到出现信号。我真的不知道如何将您的代码工作成有意义的东西......你不能在函数中分配停止通道,你必须将它传递给函数以便调用者可以监听它。就像这甚至如何编译?
func TestReceiveEvent(t *testing.T) {
createAndMonitorEvents(server.URL)
<- eventReady // undeclared variable, and discarding the event you recieved?
eventWriter.Write([]byte(someEvent)) //and another variable that is not declared
// test for something here
}
也许可以帮助您入门...
func createAndMonitorEvents(url string, done chan bool) {
//the codes
close(done)
}
func TestReceiveEvent(t *testing.T) {
eventReady := make(chan bool)
createAndMonitorEvents(server.URL, eventReady)
<- eventReady
eventWriter.Write([]byte(someEvent)) // dis still don't exist though
// test for something here
}
我认为这可以帮助
A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. Then each of the goroutines runs and calls Done when finished. At the same time, Wait can be used to block until all goroutines have finished.