首页 > 解决方案 > 测试时“无法在 Go Routine 中启动 NATS 服务器”

问题描述

我正在尝试分离测试以使用不同的 NATS 服务器。(我还不确定它是 NATS,但我的测试会相互影响。)

在运行单个测试或测试单个包时这样做可以正常工作。在我所有的包上运行go test ./...(就像在 CI 中所做的那样)我得到这个错误(路径匿名):

panic: Unable to start NATS Server in Go Routine

goroutine 1 [running]:
github.com/nats-io/gnatsd/test.RunServer(0xc000163400, 0xc000163400)
    ./go/pkg/mod/github.com/nats-io/gnatsd@v1.4.1/test/test.go:66 +0xbd
./lib/msgQueue/nats.NewTestConn(0xc0002adf68, 0x1879e12)
    ./lib/msgQueue/nats/testconn.go:19 +0x80

似乎 Go 启动了 goroutine 以在其中运行测试。使用TestMaininit在测试中都不能解决问题。

是否可以在每次测试时启动服务器而不会遇到goroutine错误?还是有一些轻量级但功能正常的内存替换?


这里有一些代码:

// +build !build

package myNats

import (
    "fmt"

    "github.com/pkg/errors"
    "github.com/nats-io/gnatsd/server"
    "github.com/nats-io/gnatsd/test"
    gonats "github.com/nats-io/go-nats"
)

type Conn struct {
    db *gonats.Conn
}

func NewTestConn() (conn *Conn, shutdown func()) {
    opts := server.Options{
        Host:   "localhost",
        Port:   53347,
        NoLog:  true,
        NoSigs: true,
    }
    gnatsd := test.RunServer(&opts)
    if gnatsd == nil {
        panic("could not start NATS test server")
    }

    url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port)
    conn, err := open(url)
    if err != nil {
        panic(errors.Wrap(err, "could not connect to test NATS"))
    }

    return conn, func() {
        conn.close()
        gnatsd.Shutdown()
    }
}

func open(addr string) (*Conn, error) {
    // Connect to NATS
    nc, err := gonats.Connect(addr)
    if err != nil {
        return nil, errors.Wrapf(err, "nats not reachable on %s", addr)
    }

    if !nc.IsConnected() {
        errorMsg := fmt.Errorf("could not establish connection to nats-server at: %s", addr)
        return nil, errorMsg
    }

    return &Conn{
        db: nc,
    }, nil
}

我的目标是每次测试都有一个服务器:

func TestSomeThing(t *testing.T) {
    conn, shutdown := myNats.NewTestConn()
    defer shutdown()

    _ = conn
    // test code here
}

标签: gotestingnats.io

解决方案


我怀疑错误信息:

Unable to start NATS Server in Go Routine

具有误导性。关于 Go Routine 的部分可能只是它如何尝试启动 NATS 服务器的实现细节。我怀疑服务器无法启动,因为您在选项中硬编码了端口,并且多个测试包可能并行运行。只有一个测试包能够绑定到端口以启动 NATS 服务器,而所有其他测试包都将失败。

标志上的文档go test说:

-parallel n
    Allow parallel execution of test functions that call t.Parallel.
    The value of this flag is the maximum number of tests to run
    simultaneously; by default, it is set to the value of GOMAXPROCS.
    Note that -parallel only applies within a single test binary.
    The 'go test' command may run tests for different packages
    in parallel as well, according to the setting of the -p flag
    (see 'go help build').

除非您在给定的测试套件中有并行测试(我假设您没有),否则问题可能是不同的包并行运行。按照上面最后的线索,让我们看一下构建标志:

-p n
    the number of programs, such as build commands or
    test binaries, that can be run in parallel.
    The default is the number of CPUs available.

这来自“编译包和依赖项”文档。请注意,您可以将构建标志测试标志传递给go test

$ go test -h
usage: go test [build/test flags] [packages] [build/test flags & test binary flags]
Run 'go help test' for details.

所以考虑跑步go test -p 1 ./...。或者,将选项传递给RunServer允许其中多个安全并行发生的函数。


推荐阅读