[英]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()
,否則它不會起作用。
我如何告訴我的測試,“除了等待一些睡眠以外,”在運行測試之前先等待其他例程完成工作? 我正在測試我的處理程序是否正確處理了該事件。
備用接口client.MonitorEvents()
返回一個通道,它為我提供了更大的控制權,但是從該通道接收信號會發出無限個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
您使用MonitorEvents
獲得nil
時,您只是看到事件通道已關閉( MonitorEvents
的源包含close(eventOrErrorChan)
,支持此操作)。 evt, ok := <-c
可讓您直接檢查是否這樣做(關閉時ok
將為假), for evt := range c
將在關閉后停止。 通常,將從封閉通道接收的數據指定為“ [已接收到任何先前發送的值后,元素類型的零值[屈服]”
關於等待回調的問題:回調可以關閉通道。 (或發送給它。)然后,您可以使用select
等待指定的時間長度:
select {
case <-c:
/* ...success... */
case <-time.After(5 * time.Second):
/* timed out */
}
如果您知道某些錯誤情況導致處理程序無法完成或無法運行,則可能會在其他通道上發信號通知這些情況,或者向c
發送不同的值。
我認為這可以幫助
WaitGroup等待goroutine的集合完成。 主goroutine調用添加以設置要等待的goroutine的數量。 然后,每個goroutine都會運行並在完成后調用Done。 同時,可以使用Wait來阻塞,直到所有goroutine完成。
“除了讓我任意睡覺之外,我如何告訴我的測試“在運行測試之前先等待其他例程完成工作”?
您可以發送一個頻道,也可以關閉一個頻道。 調用方正在接收執行塊的位置,直到出現信號為止。 我真的看不到如何將代碼工作成有意義的東西……您無法在函數中分配停止通道,必須將其傳遞給函數,以便調用者可以監聽它。 像這樣怎么編譯?
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
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.