0

0

使用 gofacto 简化 Go 集成测试:强大的模拟数据工厂

WBOY

WBOY

发布时间:2024-08-27 09:33:03

|

1009人浏览过

|

来源于dev.to

转载

使用 gofacto 简化 go 集成测试:强大的模拟数据工厂

使用数据库编写集成测试对于 web 应用程序开发至关重要,因为它增强了我们对代码的信心并确保我们的应用程序按预期工作。然而,为这些测试准备模拟数据可能具有挑战性,特别是在 go 中,它缺乏用于此任务的内置方法或标准库。本文介绍了 gofacto 库,它简化了构建模拟数据并将其插入数据库以进行 go 集成测试的过程。

 

什么是 gofacto?

gofacto 是一个 go 库,可简化模拟数据的创建和插入数据库。它提供了一种直观的方法来定义数据模式和有效处理数据库插入。借助 gofacto,开发人员可以快速准备测试数据,而无需编写大量样板代码,从而使他们能够专注于编写有意义的测试。

 

使用 gofacto 之前

让我们看看用 go 编写数据库集成测试时通常会做什么。假设我们在数据库中有一个名为 users 的表,它具有以下架构:

create table users (
    id int primary key,
    name varchar(255) not null,
    email varchar(255) not null
);

假设我们要测试一个名为 getuserbyid 的函数,该函数通过用户 id 从用户表中检索用户。为了测试这个功能,我们需要在测试这个功能之前在数据库中准备一些模拟数据。我们通常是这样做的:

type user struct {
    id      int
    gender  string
    name    string
    email   string
}

// build and insert mock user
mockuser := user{
    id:     1,
    gender: "male",
    name:   "alice",
    email:  "aaa@gmail.com",
}
err := inserttodb(mockuser)

// action
result, err := getuserbyid(mockuser.id)

// assertion
// ...

inserttodb 是一个将模拟数据插入数据库的函数。如果我们使用原始 sql 查询,可能会很复杂。

这种方法似乎易于管理,因为架构很简单,而且我们只处理一张表。

让我们看看处理两个表、用户和帖子时的情况。每个用户可以有多个帖子,表之间的关系是通过 posts 表中的 user_id 字段建立的。

create table posts (
    id int primary key,
    user_id int not null,
    title varchar(255) not null,
    content text not null,
    foreign key (user_id) references users(id)
);

假设我们要测试一个名为 getpostsbyuserid 的函数,该函数根据用户 id 从 posts 表中检索所有帖子。

type post struct {
  id      int
  userid  int
  title   string
  content string
}

// build and insert mock user
mockuser := user{
    id:     1,
    gender: "male",
    name:   "alice",
    email:  "aaa@gmail.com",
}
err := inserttodb(mockuser)

// build and insert mock post
mockpost1 := post{
  id:      1,
  userid:  mockuser.id, // manually set the foreign key
  title:   "post 1",
  content: "content 1",
}
err = inserttodb(mockpost1)

// build and insert mock post
mockpost2 := post{
  id:      2,
  userid:  mockuser.id, // manually set the foreign key
  title:   "post 2",
  content: "content 2",
}
err = inserttodb(mockpost2)

// action
result, err := getpostsbyuserid(mockuser.id)

// assertion
// ...

我们首先创建一个用户,然后为该用户创建两个帖子。与前面的示例相比,它变得更加复杂,因为我们处理两个表并建立它们之间的关系。

如果我们想为不同的用户创建多个帖子怎么办?
我们需要为每个帖子创建一个用户,这需要更多代码。

// build and insert mock user
mockuser1 := user{
  id:    1,
  gender: "male",
  name:  "alice",
  email: "aaa@gmail.com",
}
err := inserttodb(mockuser1)

// build and insert mock user
mockuser2 := user{
  id:  2,
  gender: "female",
  name:  "bob",
  email: "bbb@gmail.com",
}
err = inserttodb(mockuser2)

// build and insert mock post
mockpost1 := post{
  id:      1,
  userid:  mockuser1.id, // manually set the foreign key
  title:   "post 1",
  content: "content 1",
}
err = inserttodb(mockpost1)

// build and insert mock post
mockpost2 := post{
  id:      2,
  userid:  mockuser2.id, // manually set the foreign key
  title:   "post 2",
  content: "content 2",
}
err = inserttodb(mockpost2)

// action
result, err := getpostsbyuserid(mockuser1.id)

// assertion
// ...

当我们需要使用不同的用户和帖子创建多个模拟数据时,它会变得更加复杂且容易出错。

另请注意,我们仅使用简单的模式进行演示,实际应用中的代码会更加复杂。

 

存在哪些问题?

上面的例子中,存在一些问题:

论论App
论论App

AI文献搜索、学术讨论平台,涵盖了各类学术期刊、学位、会议论文,助力科研。

下载
  • 编写大量样板代码来准备数据库中的模拟数据
    • 有时候,我们并不关心字段的值是多少,我们只需要确保每个字段都有正确的值。
  • 对模拟数据中的 id 值进行硬编码
    • 在模拟数据中硬编码 id 的值不是一个好习惯,因为 id 通常会自动递增 数据库.
  • 手动建立表之间的关系
    • 这使得测试代码变得繁琐且容易出错,尤其是在使用多个相关表创建模拟数据时。

 

使用 gofacto

现在,让我们看看gofacto库如何帮助我们解决上述问题,让整个过程变得更加简单。

让我们看一下用户表的第一个示例。

// initialize a factory with user struct (also use `withdb` to pass the database connection)
f := gofacto.new(user{}).withdb(db)

// build and insert mock user
mockuser, err := f.build(ctx).insert()

// action
result, err := getuserbyid(mockuser.id)

// assertion
// ...

为了使用 gofacto,我们首先使用 new 函数与 user 一起初始化一个新工厂。因为我们需要将数据插入数据库,所以使用withdb将数据库连接传递给工厂。
然后,我们使用 build 函数来构建模拟数据。 insert函数将mock数据插入数据库,并以自增id返回已插入数据库的mock数据。

请注意,模拟数据的所有字段都是默认随机生成的。在这种情况下没关系,因为我们不关心字段的值。

如果我们想要指定字段的值,我们可以使用 overwrite 函数来设置字段的值。

mockuser, err := f.build(ctx).overwrite(user{gender: "male"}).insert()
// mockuser.gender == "male"

使用overwrite功能时,我们只需要指定要覆盖的字段即可。其他字段将照常随机生成。

让我们看看我们想要用一个用户创建多个帖子的情况。
为了让 gofacto 知道表之间的关系,我们需要在结构体中定义正确的标签。

type post struct {
    id      int
    userid  int       `gofacto:"foreignkey,struct:user"`
    title   string
    content string
}

标签告诉 gofacto userid 字段是引用 user 结构体的 id 字段的外键。

现在,我们可以轻松地用一个用户创建多个帖子。

mockuser := user{}
mockposts, err := f.buildlist(ctx, 2).withone(&mockuser).insert() // must pass pointer to the struct to `withone`
// mockposts[0].userid == mockuser.id
// mockposts[1].userid == mockuser.id

// action
result, err := getpostsbyuserid(mockuser.id)

// assertion
// ...

为了创建多个帖子,我们使用 buildlist 函数以及我们想要创建的帖子数量。然后,我们使用 withone 函数来指定所有帖子都属于一个用户。 insert 函数返回已插入数据库且 id 自动递增的帖子列表。

gofacto 库确保所有字段都正确随机设置,并且表之间的关系正确建立。

让我们看看我们想要为不同用户创建多个帖子的情况。

mockUser1 := User{}
mockUser2 := User{}
mockPosts, err := f.BuildList(ctx, 2).WithMany([]interface{}{&mockUser1, &mockUser2}).Insert()
// mockPosts[0].UserID == mockUser1.ID
// mockPosts[1].UserID == mockUser2.ID

// action
result, err := getPostsByUserID(mockUser1.ID)

// assertion
// ...

我们使用 withmany 函数来指定每个帖子与不同的用户关联。

 

概括

我们已经看到了 gofacto 如何简化在 go 中编写数据库集成测试。它减少了样板代码,使准备多个表的模拟数据并在它们之间建立关系变得更加容易。最重要的是,gofacto 抽象了准备模拟数据的复杂性,使开发人员能够专注于编写有意义的测试。 要开始在 go 项目中使用 gofacto,请访问 github 存储库以获取安装说明和更详细的文档。

 

反馈和进一步发展

作为一名新的库开发人员,我很想听听您对 gofacto 的想法!如有任何反馈、建议或批评,我们表示赞赏。如果您在 go 项目中使用它,请分享您的经验。发现错误或有想法?在 gofacto github 存储库上打开问题。想贡献代码吗?欢迎拉取请求!您的反馈和贡献将有助于改进 gofacto 并使 go 社区受益。感谢您查看!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

751

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

328

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

350

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1304

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

361

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

881

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

581

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

425

2024.04.29

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

32

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 3.2万人学习

Git版本控制工具
Git版本控制工具

共8课时 | 1.5万人学习

Git中文开发手册
Git中文开发手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号