我正在尝试使用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
型
有什么方法可以解决这个问题吗?提前谢谢你!
1条答案
按热度按时间fcg9iug31#
@pizhlo,你可能想看看Postgres模块:https://golang.testcontainers.org/modules/postgres/
主要的区别是模块带有预定义的等待策略,我认为这是测试失败的根本原因:你定义了一个等待端口可用的等待策略,但是我们在内部检查Postgres日志是否包含两次“数据库系统准备接受连接”条目。
在你的代码中,我会先尝试这个等待策略:
字符串
或者只是切换到模块,通过导入模块来减少代码。