正则匹配
- sqlmock中默认使用的是正则表达式去匹配sql语句
如sqlmock.ExpectQuery()
和sqlmock.ExpectExec()
等,如果想直接匹配sql语句需要加上regexp.QuoteMeta()
例子:
//这个是使用正则来匹配sql语句,需要使用“\\”来转义字符
mock.ExpectQuery("SELECT \\* FROM `cmdb_app` WHERE app_code = \\? AND is_deleted = \\? ORDER BY `cmdb`\\.`id` limit 1")
//直接匹配sql语句
mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM `cmdb_app` WHERE app_code = ? AND is_deleted = ? ORDER BY `cmdb`.`id` limit 1"))
mock所有的sql语句
当我想测试一个在mysql中创建app记录的函数时,我只模拟了insert语句的返回情况,忽略了创建app记录前还有个select语句判断当前数据库中是否已有app记录
当前的代码:
mock.ExpectBegin()
mock.ExpectExec("INSERT INTO").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
所以导致了下面这个错误
call to Query 'SELECT * FROM `cmdb_app` WHERE app_code = ? and is_deleted = 0 ORDER BY `cmdb_app`.`id` LIMIT 1' with args [{Name: Ordinal:1 Value:app1}], was not expected, next expectation is: ExpectedExec => expecting Exec or ExecContext which:
- matches sql: 'INSERT INTO'
- is without arguments
- should return Result having:
LastInsertId: 1
RowsAffected: 1
修改代码
// 在mock.ExpectExec("INSERT INTO")之前加上下面代码
mock.ExpectQuery("SELECT").WillReturnRows(sqlmock.NewRows([]string{"id", "app_code", "app_name", "status", "business", "app_type", "desc", "language"}))
运行成功:
=== RUN TestCreateApp
--- PASS: TestCreateApp (0.00s)
=== RUN TestCreateApp/create_success
--- PASS: TestCreateApp/create_success (0.00s)
PASS
注意关闭内联优化
有时会遇到mock失效的情况,这个问题一般是内联导致的。
什么是内联?
为了减少函数调用时的堆栈等开销,对于简短的函数,会在编译时,直接内嵌调用的代码。
如下面例子未使用内联优化:
[root@DESKTOP-GG9HG4Q cmdb_service]# go test
E
Errors:
* /root/Projections/Athena/src/service/cmdb_service/cmdb_environment_test.go
Line 167: - runtime error: invalid memory address or nil pointer dereference
goroutine 8 [running]:
/home/gopath/pkg/mod/github.com/smartystreets/goconvey@v1.6.4/convey/reporting/reports.go:148 +0x6f
/home/gopath/pkg/mod/github.com/smartystreets/goconvey@v1.6.4/convey/reporting/reports.go:121 +0x75
/home/gopath/pkg/mod/github.com/smartystreets/goconvey@v1.6.4/convey/context.go:235 +0x13f
加上-gcflags=all=-l
后关闭内联优化
[root@DESKTOP-GG9HG4Q cmdb_service]# go test -gcflags=all=-l
.
1 total assertion
PASS
ok athena/src/service/cmdb_service 0.005s