Go语言 尝试使用testcontainers测试我的数据库,但得到了一个运行时错误:索引超出范围

ryevplcw  于 12个月前  发布在  Go
关注(0)|答案(1)|浏览(134)

我正在尝试使用testcontainers测试我的数据库。我从https://gist.github.com/Eun/221e9cb9190b56578dbb752e5e2a6b2a复制了一些代码,并按照我需要的方式编辑了它:

type TestNoteEditor struct {
    db *gorm.DB
    NoteEditor
    instance testcontainers.Container
}

type TestDatabase struct {
    instance testcontainers.Container
}

const DBSource = "postgresql://%s:%s@%s/%d?sslmode=disable"

func NewTestDatabase(t *testing.T) *TestNoteEditor {
    ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
    defer cancel()

    req := testcontainers.ContainerRequest{
        Image:        "postgres:12",
        ExposedPorts: []string{"5432/tcp"},
        AutoRemove:   true,
        Env: map[string]string{
            "POSTGRES_USER":     "postgres",
            "POSTGRES_PASSWORD": "postgres",
            "POSTGRES_DB":       "postgres",
        },
        WaitingFor: wait.ForListeningPort("5432/tcp"),
    }

// the error occurs on the line below
    postgresContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
        ContainerRequest: req,
        Started:          true,
    })
    if err != nil {
        t.Fatal("GenericContainer err = ", err)
    }

    require.NoError(t, err)

    testDb := TestDatabase{instance: postgresContainer}
    port := testDb.Port(t)
    source := fmt.Sprintf(DBSource, "postgres", "postgres", "postgres", port)

    db, err := gorm.Open(postgres.Open(source), &gorm.Config{})
    if err != nil {
        log.Fatal().Msg("cannot create gorm")
    }

    return &TestNoteEditor{
        db:       db,
        instance: postgresContainer,
    }
}

func (db *TestDatabase) Port(t *testing.T) int {
    ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
    defer cancel()
    p, err := db.instance.MappedPort(ctx, "5432")
    require.NoError(t, err)
    return p.Int()
}

func (db *TestDatabase) ConnectionString(t *testing.T) string {
    return fmt.Sprintf("postgres://postgres:[email protected]:%d/postgres", db.Port(t))
}

func (db *TestDatabase) Close(t *testing.T) {
    ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
    defer cancel()
    require.NoError(t, db.instance.Terminate(ctx))
}

字符串
下面是我如何运行这段代码:

func TestDatabase_SaveNote(t *testing.T) {
    type args struct {
        n notes.UserNoteRequest
    }
    tests := []struct {
        name    string
        db      *TestNoteEditor
        args    args
        want    Note
        wantErr bool
    }{
        {
            name: "positive test",
            db:   &TestNoteEditor{},
            args: args{
                n: notes.UserNoteRequest{
                    User:   297850814,
                    Title:  "test #1",
                    Photos: []notes.UserPhoto{},
                },
            },
            want: Note{
                ID:       1,
                User:     1,
                Title:    "test #1",
                Created:  time.Now(),
                HasPhoto: false,
            },
            wantErr: false,
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {

            tt.db = NewTestDatabase(t)
        })
    }
}


但是当我运行这段代码时,我总是在NewTestDatabase函数中得到一个错误。下面是错误:

2023/07/07 18:00:34 Starting container id: c952804c376e image: quay.io/testcontainers/ryuk:0.2.3
2023/07/07 18:00:34 Waiting for container id c952804c376e image: quay.io/testcontainers/ryuk:0.2.3
--- FAIL: TestDatabase_SaveNote (0.47s)
    --- FAIL: TestDatabase_SaveNote/positive_test (0.47s)
panic: runtime error: index out of range [0] with length 0 [recovered]
    panic: runtime error: index out of range [0] with length 0

goroutine 23 [running]:
testing.tRunner.func1.2({0xb690a0, 0xc0001120a8})
    C:/Users/pizhlo21/golang/go1.20rc3/go1.20rc3/src/testing/testing.go:1526 +0x24e
testing.tRunner.func1()
    C:/Users/pizhlo21/golang/go1.20rc3/go1.20rc3/src/testing/testing.go:1529 +0x39f
panic({0xb690a0, 0xc0001120a8})
    C:/Users/pizhlo21/golang/go1.20rc3/go1.20rc3/src/runtime/panic.go:884 +0x213
github.com/testcontainers/testcontainers-go.(*DockerContainer).MappedPort(0xcc4658?, {0xcc45e8, 0xc00017a000}, {0xbb5d29, 0x8})
    C:/Users/pizhlo21/Desktop/Folder/golang/pkg/mod/github.com/testcontainers/[email protected]/docker.go:128 +0x2e5
github.com/testcontainers/testcontainers-go/wait.(*HostPortStrategy).WaitUntilReady(0xc0000082a0, {0xcc4658?, 0xc0003ec510?}, {0xcc4850, 0xc00026a000})
    C:/Users/pizhlo21/Desktop/Folder/golang/pkg/mod/github.com/testcontainers/[email protected]/wait/host_port.go:59 +0x11a
github.com/testcontainers/testcontainers-go.(*DockerContainer).Start(0xc00026a000, {0xcc4658, 0xc0003ec510})
    C:/Users/pizhlo21/Desktop/Folder/golang/pkg/mod/github.com/testcontainers/[email protected]/docker.go:160 +0x1bc
github.com/testcontainers/testcontainers-go.(*DockerProvider).RunContainer(_, {_, _}, {{{0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0}}, {0xbca790, ...}, ...})
    C:/Users/pizhlo21/Desktop/Folder/golang/pkg/mod/github.com/testcontainers/[email protected]/docker.go:642 +0x95
github.com/testcontainers/testcontainers-go.NewReaper({0xcc4658, 0xc0003ec510}, {0xc00017d920, 0x24}, {0xcbc2c0, 0xc000008258}, {0x0, 0x0})
    C:/Users/pizhlo21/Desktop/Folder/golang/pkg/mod/github.com/testcontainers/[email protected]/reaper.go:73 +0x44d
github.com/testcontainers/testcontainers-go.(*DockerProvider).CreateContainer(_, {_, _}, {{{0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0}}, {0xbb82a8, ...}, ...})
    C:/Users/pizhlo21/Desktop/Folder/golang/pkg/mod/github.com/testcontainers/[email protected]/docker.go:479 +0x385
github.com/testcontainers/testcontainers-go.GenericContainer({_, _}, {{{{0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0}}, {0xbb82a8, 0xb}, ...}, ...})
    C:/Users/pizhlo21/Desktop/Folder/golang/pkg/mod/github.com/testcontainers/[email protected]/generic.go:43 +0x89
github.com/Pizhlo/tgbot-reminder-go/internal/db/postgresql.NewTestDatabase(0xc0002669c0)
    c:/Users/pizhlo21/Desktop/Folder/golang/TgBotReminder/internal/db/postgresql/main_test.go:42 +0x2d1
github.com/Pizhlo/tgbot-reminder-go/internal/db/postgresql.TestDatabase_SaveNote.func1(0x0?)
    c:/Users/pizhlo21/Desktop/Folder/golang/TgBotReminder/internal/db/postgresql/notes_test.go:45 +0x25
testing.tRunner(0xc0002669c0, 0xc0001ca5e0)
    C:/Users/pizhlo21/golang/go1.20rc3/go1.20rc3/src/testing/testing.go:1576 +0x10b
created by testing.(*T).Run
    C:/Users/pizhlo21/golang/go1.20rc3/go1.20rc3/src/testing/testing.go:1629 +0x3ea
FAIL    github.com/Pizhlo/tgbot-reminder-go/internal/db/postgresql  0.890s
FAIL


有什么方法可以解决这个问题吗?提前谢谢你!

fcg9iug3

fcg9iug31#

@pizhlo,你可能想看看Postgres模块:https://golang.testcontainers.org/modules/postgres/
主要的区别是模块带有预定义的等待策略,我认为这是测试失败的根本原因:你定义了一个等待端口可用的等待策略,但是我们在内部检查Postgres日志是否包含两次“数据库系统准备接受连接”条目。
在你的代码中,我会先尝试这个等待策略:

wait.ForLog("database system is ready to accept connections").
            WithOccurrence(2).
            WithStartupTimeout(5*time.Second))

字符串
或者只是切换到模块,通过导入模块来减少代码。

相关问题