You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
❯ go test -v
=== RUN TestShouldUpdateStats
--- PASS: TestShouldUpdateStats (0.00s)
=== RUN TestShouldRollbackStatUpdatesOnFailure
--- PASS: TestShouldRollbackStatUpdatesOnFailure (0.00s)
PASS
ok golang-unit-test-demo/sqlmock_demo 0.011s
这是Go语言单元测试系列教程的第3篇,介绍了如何使用
go-sqlmock
和miniredis
工具进行MySQL
和Redis
的mock
测试。在上一篇《Go单元测试--模拟服务请求和接口返回》中,我们介绍了如何使用httptest和gock工具进行网络测试。
除了网络依赖之外,我们在开发中也会经常用到各种数据库,比如常见的MySQL和Redis等。本文就分别举例来演示如何在编写单元测试的时候对MySQL和Redis进行mock。
go-sqlmock
sqlmock 是一个实现
sql/driver
的mock库。它不需要建立真正的数据库连接就可以在测试中模拟任何 sql 驱动程序的行为。使用它可以很方便的在编写单元测试的时候mock sql语句的执行结果。安装
使用示例
这里使用的是
go-sqlmock
官方文档中提供的基础示例代码。在下面的代码中,我们实现了一个recordStats
函数用来记录用户浏览商品时产生的相关数据。具体实现的功能是在一个事务中进行以下两次SQL操作:products
表中将当前商品的浏览次数+1product_viewers
表中记录浏览当前商品的用户id现在我们需要为代码中的
recordStats
函数编写单元测试,但是又不想在测试过程中连接真实的数据库进行测试。这个时候我们就可以像下面示例代码中那样使用sqlmock
工具去mock数据库操作。上面的代码中,定义了一个执行成功的测试用例和一个执行失败回滚的测试用例,确保我们代码中的每个逻辑分支都能被测试到,提高单元测试覆盖率的同时也保证了代码的健壮性。
执行单元测试,看一下最终的测试结果。
可以看到两个测试用例的结果都符合预期,单元测试通过。
在很多使用ORM工具的场景下,也可以使用
go-sqlmock
库mock数据库操作进行测试。miniredis
除了经常用到MySQL外,Redis在日常开发中也会经常用到。接下来的这一小节,我们将一起学习如何在单元测试中mock Redis的相关操作。
miniredis是一个纯go实现的用于单元测试的redis server。它是一个简单易用的、基于内存的redis替代品,它具有真正的TCP接口,你可以把它当成是redis版本的
net/http/httptest
。当我们为一些包含Redis操作的代码编写单元测试时就可以使用它来mock Redis操作。
安装
使用示例
这里以
github.com/go-redis/redis
库为例,编写了一个包含若干Redis操作的DoSomethingWithRedis
函数。下面的代码是我使用
miniredis
库为DoSomethingWithRedis
函数编写的单元测试代码,其中miniredis
不仅支持mock常用的Redis操作,还提供了很多实用的帮助函数,例如检查key的值是否与预期相等的s.CheckGet()
和帮助检查key过期时间的s.FastForward()
。执行执行测试,查看单元测试结果:
miniredis
基本上支持绝大多数的Redis命令,大家可以通过查看文档了解更多用法。当然除了使用
miniredis
搭建本地redis server这种方法外,还可以使用各种打桩工具对具体方法进行打桩。在编写单元测试时具体使用哪种mock方式还是要根据实际情况来决定。总结
在日常工作开发中为代码编写单元测试时如何处理数据库的依赖是最常见的问题,本文介绍了如何使用
go-sqlmock
和miniredis
工具mock相关依赖。在下一篇中,我们将更进一步,详细介绍如何在编写单元测试时mock接口实现。
相关阅读
The text was updated successfully, but these errors were encountered: