我想测试一些通常需要网络访问的cobra.Commands {}。我想模拟网络部分,但是我很难找到一种模式,该模式可以让我编写小型接口,并且仍然可以执行我想做的事情。
cobra.Command将仅运行带有签名的功能(* cobra.Command,args []字符串)。这限制了我如何传入网络客户端(或模拟的网络客户端)。
网络客户端不能是程序包变量,因为viper需要首先解析命令行参数。所以我有一个功能:
func newNode() otherpkg.NodeInterface {
return otherpkg.NewNode(otherpkg.Config.Node.URL, debug)
}
newNode()仅是网络,因此我在测试时需要解决它。我将网络初始化保留在cobra.Command的匿名函数中,然后将实际逻辑移至ttlFunc()。我只测试ttlFunc,不测试ttlCmd。这样,我可以测试实际逻辑或使用GetHeighter接口传递模拟网络客户端。
var ttlCmd = &cobra.Command{
Use: "ttl",
Short: "Get the absolute TTL for a Transaction",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
node := newNode()
return ttlFunc(node, args)
},
}
func ttlFunc(conn otherpkg.GetHeighter, args []string) (err error) {
height, err := conn.GetHeight()
if err != nil {
errFinal := fmt.Errorf("Error getting height from the node: %v", err)
return errFinal
}
ttl = height + otherpkg.Config.Client.TTL
fmt.Println(ttl)
return nil
}
如果现在模拟了conn.GetHeight,则可以看到在ttlFunc()之类的简单函数中,如果仅从函数返回错误,则不会进行任何测试。因此,我想使用cobra.Command SetIn(),SetOut()并测试ttlCmd,并针对stdout进行断言。
但是,如果我离开了ttlCmd()/ ttlFunc()模式,那么我不知道如何在不混合测试代码和有用代码的情况下,将客户端/模拟客户端提供给需要的函数像这样:
func newNode() otherpkg.NodeInterface {
if !online{
return &MockNode{}
}
return otherpkg.NewNode(otherpkg.Config.Node.URL, debug)
}
另外,otherpkg.NodeInterface很大,因此MockNode将自己维护。我知道在Go中应该保持接口较小,但是此newNode()应该为每个cobra.Command服务。我该怎么办?