测试模拟
在为调用 Go 客户端使用的方法的函数编写测试时,通常需要运行一个真实的数据库才能使这些测试正常工作。虽然这对于集成测试是可以接受的,但由于需要重置和迁移数据库、播种数据,然后关闭所有内容,因此测试代码可能更难。此外,这会导致测试运行速度非常慢。
Prisma 提供了原生模拟,以便在单元测试中注入任何你想要的内容。这样,你可以为每个查询定义要返回的结果,然后使用这些信息测试你的函数。它们也很快,因为不需要真实的数据库,你只需自己定义函数应该返回什么。
这些示例使用以下 Prisma 模式
model Post {
id String @default(cuid()) @id
title String
}
测试结果
函数 GetPostTitle
充当你的解析器;例如,它可以是 API 路由中调用的函数。
要编写单元测试,你需要创建一个新的 Prisma 模拟客户端,定义你的期望,然后运行你的实际测试。期望包括你期望的精确查询或查询,以及应该返回的结果。
// main.go
func GetPostTitle(ctx context.Context, client *PrismaClient, postID string) (string, error) {
post, err := client.Post.FindUnique(
db.Post.ID.Equals(postID),
).Exec(ctx)
if err != nil {
return "", fmt.Errorf("error fetching post: %w", err)
}
return post.Title, nil
}
// main_test.go
func TestGetPostTitle_returns(t *testing.T) {
// create a new mock
// this returns a mock prisma `client` and a `mock` object to set expectations
client, mock, ensure := NewMock()
// defer calling ensure, which makes sure all of the expectations were met and actually called
// calling this makes sure that an error is returned if there was no query happening for a given expectation
// and makes sure that all of them succeeded
defer ensure(t)
expected := db.PostModel{
InnerPost: db.InnerPost{
ID: "123",
Title: "foo",
},
}
// start the expectation
mock.Post.Expect(
// define your exact query as in your tested function
// call it with the exact arguments which you expect the function to be called with
// you can copy and paste this from your tested function, and just put specific values into the arguments
client.Post.FindUnique(
db.Post.ID.Equals("123"),
),
).Returns(expected) // sets the object which should be returned in the function call
// mocking set up is done; let's define the actual test now
title, err := GetPostTitle(context.Background(), client, "123")
if err != nil {
t.Fatal(err)
}
if title != "foo" {
t.Fatalf("title expected to be foo but is %s", title)
}
}
测试错误
你还可以使用 Errors
函数模拟客户端为给定查询返回错误。
// main_test.go
func TestGetPostTitle_error(t *testing.T) {
client, mock, ensure := NewMock()
defer ensure(t)
mock.Post.Expect(
client.Post.FindUnique(
db.Post.ID.Equals("123"),
),
).Errors(db.ErrNotFound)
_, err := GetPostTitle(context.Background(), client, "123")
if !errors.Is(err, ErrNotFound) {
t.Fatalf("error expected to return ErrNotFound but is %s", err)
}
}