我有一个应用程序 (epazote),一旦启动就永远运行,但我想在它阻塞/等待直到按下 ctrl+c 之前测试一些值或被杀了。
这是一个小例子:http://play.golang.org/p/t0spQRJB36
package main
import (
"fmt"
"os"
"os/signal"
)
type IAddString interface {
AddString(string)
}
type addString struct{}
func (self *addString) AddString(s string) {
fmt.Println(s)
}
func block(a IAddString, s string) {
// test this
a.AddString(s)
// ignore this while testing
block := make(chan os.Signal)
signal.Notify(block, os.Interrupt, os.Kill)
for {
signalType := <-block
switch signalType {
default:
signal.Stop(block)
fmt.Printf("%q signal received.", signalType)
os.Exit(0)
}
}
}
func main() {
a := &addString{}
block(a, "foo")
}
我想知道在测试时是否可以忽略代码的某些部分,或者如何测试这种情况,我已经实现了一个接口(interface),在这种情况下用于测试对我有帮助的 AddString
测试某些部分,但不知道如何避免“阻塞”并进行测试。
有什么想法吗?
更新:将代码放在循环 Addstring
中的另一个函数中有效,但仅用于测试该函数,但如果我想做完整的代码覆盖,我仍然需要检查/测试阻塞部分,例如如何测试接收 ctrl+c 或 kill -HUP
时行为是否正常,我正在考虑创建一个假的 signal.Notify
但不知道如何覆盖导入的包以防万一。
最佳答案
在您的代码中引入测试委托(delegate)。
将您的循环提取为一个函数,该函数接受 2 个函数作为参数:onBeginEvent 和 onEndEvent。函数签名应采用:
- 声明您要在测试用例中检查
- 可选:循环编号计数器(以便您识别每个循环)。它是可选的,因为实际的委托(delegate)实现可以计算它自己调用的次数。
在循环开始时调用 OnBegingEvent(counter, currentState);比您的代码正常工作,最后您调用 OnEndEvent(counter, currentState);大概你的代码已经改变了 currentState。
在生产中,您可以使用函数委托(delegate)的空实现或在循环中实现 nil 检查。
您可以根据需要使用此模型对处理算法进行尽可能多的检查。假设您有 5 张支票。现在你回过头来看它并意识到这变得太难了。您创建一个定义回调函数的接口(interface)。这些回调函数是改变服务行为的强大方法。你再退一步,意识到接口(interface)实际上是你的“服务策略”;)
一旦你走这条路,你就会想以某种方式停止你的无限循环。如果您想在测试用例中进行严格控制,您可以采用第三个函数委托(delegate),如果是时候退出循环,则返回 true。共享变量是控制退出条件的一个选项。
这肯定是比单元测试更高级别的测试,并且在复杂的服务中是必要的。
关于unit-testing - 如何测试永远循环的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35004276/