如何在测试中在goroutine中测试结果而无需等待?

huangapple go评论151阅读模式
英文:

how to test the result in goroutine without wait in test

问题

当我在使用golang时,有时候需要在goroutine中测试结果,我之前使用time.Sleep来测试,我想知道是否有更好的方法来进行测试。

假设我有如下的示例代码:

func Hello() {
	go func() {
		// 做一些事情,并将结果存储在数据库中
	}()
	// 做一些其他事情
}

当我测试这个函数时,我想要同时测试goroutine中的结果,我目前是这样做的:

func TestHello(t *testing.T) {
	Hello()
	time.Sleep(time.Second) // 等待一段时间,以便goroutine完成
	// 测试goroutine的结果
}

是否有更好的方法来进行这个测试?

基本上,在实际逻辑中,我不关心goroutine中的结果,我不需要等待它完成。但是在测试中,我想要在它完成后进行检查。

英文:

When I do ut of golang, I sometimes need to test the result in goroutine, I was using time.Sleep to test, I am wondering is there any better way to test.

let's say I have an example code like this

func Hello() {
	go func() {
		// do something and store the result for example in db
	}()
	// do something
}

Then when I test the func, I want to test both result in goroutine,
I am doing this:

 func TestHello(t *testing.T) {
    	Hello()
    	time.Sleep(time.Second) // sleep for a while so that goroutine can finish
        // test the result of goroutine
 }

is there any better way to test this?

Basically, in real logic, I don't care the result in goroutine, I don't need to wait for it finished. but in test, I want to check after it finished.

答案1

得分: 7

大多数关于“如何测试X?”的问题往往归结为X太大。

在你的情况下,最简单的解决方案是在测试中不使用goroutines。将每个函数单独进行测试。将你的代码更改为:

func Hello() {
    go updateDatabase()
    doSomething()
}

func updateDatabase() {
    // 做一些事情并将结果存储在数据库中
}

func doSomething() {
    // 做一些事情
}

然后为updateDatabasedoSomething编写单独的测试。

英文:

Most questions of "How do I test X?" tend to boil down to X being too big.

In your case, the simplest solution is not to use goroutines in tests. Test each function in isolation. Change your code to:

func Hello() {
    go updateDatabase()
    doSomething()
}

func updateDatabase() {
    // do something and store the result for example in db
}

func doSomething() {
    // do something
}

Then write separate tests for updateDatabase and doSomething.

答案2

得分: 6

如果你真的想要检查一个goroutine的结果,你应该使用一个通道,像这样:

package main

import (
	"fmt"
)

func main() {
	// 在测试中
	c := Hello()
	if <-c != "done" {
		fmt.Println("assert error")
	}

	// 不想检查结果
	Hello()
}

func Hello() <-chan string {
	c := make(chan string)
	go func() {
		fmt.Println("做一些事情")
		c <- "done"
	}()
	return c
}

你可以在这里查看代码:https://play.golang.org/p/zUpNXg61Wn

英文:

If you really want to check the result of a goroutine, you should use a channel like so:

package main

import (
	&quot;fmt&quot;
)

func main() {
	// in test
	c := Hello()
	if &lt;-c != &quot;done&quot; {
		fmt.Println(&quot;assert error&quot;)
	}

	// not want to check result
	Hello()
}

func Hello() &lt;-chan string {
	c := make(chan string)
	go func() {
		fmt.Println(&quot;do something&quot;)
		c &lt;- &quot;done&quot;
	}()
	return c
}

https://play.golang.org/p/zUpNXg61Wn

huangapple
  • 本文由 发表于 2017年9月12日 10:49:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/46167142.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定