搜索
首页后端开发Golang使用 go-sqlmock 测试 gorm 问题,将查询与mock.ExpectQuery 和 regexp.QuoteMeta 进行比较

使用 go-sqlmock 测试 gorm 问题,将查询与mock.ExpectQuery 和 regexp.QuoteMeta 进行比较

在开发过程中,使用 go-sqlmock 来测试 gorm 的问题是一种常见的需求。go-sqlmock 是一个用于模拟数据库操作的工具,而 gorm 则是一个流行的 Go 语言 ORM 库。在测试过程中,我们经常需要比较查询语句是否符合预期。为了做到这一点,我们可以使用 mock.ExpectQuery 和 regexp.QuoteMeta 来进行比较。这种方法能够帮助我们更好地测试和调试代码,确保程序的正确性和稳定性。接下来,我们将详细介绍如何使用 go-sqlmock 进行 gorm 测试,并展示如何使用 mock.ExpectQuery 和 regexp.QuoteMeta 进行查询语句的比较。

问题内容

我在比较预期查询与 gorm 的真实查询时遇到问题,这是我的代码:

package repository

import (
    "regexp"
    "testing"

    "github.com/data-dog/go-sqlmock"
    "your_go_root/pkg/domain"
    "github.com/stretchr/testify/assert"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)


var successgettransaction domain.transaction = domain.transaction{
    id:          2,
    buyerid:     2,
    sellerid:    5,
    itemid:      2,
    messageid:   2,
    expireddate: "2022-09-010 01:01:00",
    createdat:   "2022-09-08 01:01:00",
}

func testsuccessgettransactionbyid(t *testing.t) {

    db, mock, err := sqlmock.new()
    assert.noerror(t, err)
    gdb, err := gorm.open(mysql.new(mysql.config{
        conn:                      db,
        skipinitializewithversion: true,
    }), &gorm.config{})
    assert.noerror(t, err)

    rows := sqlmock.newrows([]string{"id", "buyer_id", "seller_id", "item_id", "message_id", "expired_date", "created_at"}).
        addrow(2, 2, 5, 2, 2, "2022-09-010 01:01:00", "2022-09-08 01:01:00")
    mock.expectquery(regexp.quotemeta("select * from transaction where id = ?;")).willreturnrows(rows)

    repo := defaultclient(gdb)
    actualsectionlist, _ := repo.gettransactionbyid(2)
    
    assert.equal(t, successgettransaction, actualsectionlist, "ambas listas deberian ser iguales")
    assert.noerror(t, mock.expectationsweremet())
}

这是模块域:

package domain

type transaction struct {
    id          int64  `gorm:"primarykey;column:id"`
    buyerid     int64  `gorm:"column:buyer_id"`
    sellerid    int64  `gorm:"column:seller_id"`
    itemid      int    `gorm:"column:item_id"`
    messageid   int    `gorm:"column:message_id"`
    expireddate string `gorm:"column:expired_date"`
    createdat   string `gorm:"column:created_at"`
}

func (transaction) tablename() string {
    return "transaction"
}

type transactionstatus struct {
    id             int64  `gorm:"primarykey;column:id"`
    transactionid  int64  `gorm:"column:transaction_id"`
    status         int    `gorm:"column:status"`
    notificationid int    `gorm:"column:notification_id"`
    createdat      string `gorm:"column:created_at"`
}

func (transactionstatus) tablename() string {
    return "transaction_status"
}

这是我正在测试的功能:

package repository

import (
    "fmt"

    "your_go_root/pkg/domain"
    "gorm.io/gorm"
)

type repositoryclient interface {
    gettransactionbyid(id int) (domain.transaction, error)
}

type repositoryclient struct {
    db *gorm.db
}

func defaultclient(db *gorm.db) repositoryclient {
    return &repositoryclient{
        db: db,
    }
}

func (rc repositoryclient) gettransactionbyid(id int) (domain.transaction, error) {
    trans := domain.transaction{}
    status := rc.db.where("id = ?", id).find(&trans)

    if status.error != nil {
        return domain.transaction{}, status.error
    }
    if trans == (domain.transaction{}) {
        return domain.transaction{}, fmt.errorf("error finding transaction id %v", id)
    }
    return trans, nil
}

这是我从控制台收到的错误:

Query: could not match actual sql: "SELECT * FROM `transaction` WHERE id = ?" with expected regexp "SELECT \* FROM transaction WHERE id = \?;"[0m[33m[0.218ms] [34;1m[rows:0][0m SELECT * FROM `transaction` WHERE id = 2

在本节中存在一个用“select(.*)”替代的答案,但根据我读到的内容,这不是真正的解决方案

解决方法

让我尝试帮助解决这个问题。我下载了您的所有文件,并且 domain.gorepository.go 对我来说看起来不错。
但是,我在 repository_test.go 文件中发现了一些小问题:

  1. 您编写的 sql 查询中缺少反引号
  2. 查询末尾额外的 ;
  3. 缺少对 withargs(2) 方法的调用

如果您调整了这些小问题,您应该得到如下所示的代码:

// ... omitted for brevity
func TestSuccessGetTransactionByID(t *testing.T) {
    db, mock, err := sqlmock.New()
    assert.NoError(t, err)
    gdb, err := gorm.Open(mysql.New(mysql.Config{
        Conn:                      db,
        SkipInitializeWithVersion: true,
    }), &gorm.Config{})
    assert.NoError(t, err)

    rows := sqlmock.NewRows([]string{"id", "buyer_id", "seller_id", "item_id", "message_id", "expired_date", "created_at"}).AddRow(2, 2, 5, 2, 2, "2022-09-010 01:01:00", "2022-09-08 01:01:00")
    mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM `transaction` WHERE id = ?")).WithArgs(2).WillReturnRows(rows)

    repo := DefaultClient(gdb)
    actualSectionList, _ := repo.GetTransactionByID(2)

    assert.Equal(t, successGetTransaction, actualSectionList, "ambas listas deberian ser iguales")
    assert.NoError(t, mock.ExpectationsWereMet())
}

然后,如果您尝试运行测试,它应该可以工作。
如果这解决了您的问题,请告诉我,谢谢!

以上是使用 go-sqlmock 测试 gorm 问题,将查询与mock.ExpectQuery 和 regexp.QuoteMeta 进行比较的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:stackoverflow。如有侵权,请联系admin@php.cn删除
学习GO String操纵:使用'字符串”软件包学习GO String操纵:使用'字符串”软件包May 09, 2025 am 12:07 AM

Go的"strings"包提供了丰富的功能,使字符串操作高效且简单。1)使用strings.Contains()检查子串。2)strings.Split()可用于解析数据,但需谨慎使用以避免性能问题。3)strings.Join()适用于格式化字符串,但对小数据集,循环使用 =更有效。4)对于大字符串,使用strings.Builder构建字符串更高效。

GO:使用标准'字符串”包的字符串操纵GO:使用标准'字符串”包的字符串操纵May 09, 2025 am 12:07 AM

Go语言使用"strings"包进行字符串操作。1)拼接字符串使用strings.Join函数。2)查找子串使用strings.Contains函数。3)替换字符串使用strings.Replace函数,这些函数高效且易用,适用于各种字符串处理任务。

使用GO的'字节”软件包掌握字节切片操作:实用指南使用GO的'字节”软件包掌握字节切片操作:实用指南May 09, 2025 am 12:02 AM

资助bytespackageingoisesential foreffited byteSemanipulation,uperingFunctionsLikeContains,index,andReplaceForsearchingangingAndModifyingBinaryData.itenHancesperformanceNandCoderAceAnibility,MakeitiTavitalToolToolToolToolToolToolToolToolToolForhandLingBinaryData,networkProtocols,networkProtocoLss,networkProtocols,andetFilei

学习GO二进制编码/解码:使用'编码/二进制”软件包学习GO二进制编码/解码:使用'编码/二进制”软件包May 08, 2025 am 12:13 AM

Go语言使用"encoding/binary"包进行二进制编码与解码。1)该包提供binary.Write和binary.Read函数,用于数据的写入和读取。2)需要注意选择正确的字节序(如BigEndian或LittleEndian)。3)数据对齐和错误处理也是关键,确保数据的正确性和性能。

GO:带有标准'字节”软件包的字节切​​片操作GO:带有标准'字节”软件包的字节切​​片操作May 08, 2025 am 12:09 AM

1)usebybytes.joinforconcatenatinges,2)bytes.bufferforincrementalWriter,3)bytes.indexorbytes.indexorbytes.indexbyteforsearching bytes.bytes.readereforrednerncretinging.isnchunk.ss.ind.inc.softes.4)

进行编码/二进制包:优化二进制操作的性能进行编码/二进制包:优化二进制操作的性能May 08, 2025 am 12:06 AM

theencoding/binarypackageingoiseforporptimizingBinaryBinaryOperationsDuetoitssupportforendiannessessandefficityDatahandling.toenhancePerformance:1)usebinary.nativeendiandiandiandiandiandiandiandian nessideendian toavoid avoidByteByteswapping.2)

Go Bytes软件包:简短的参考和提示Go Bytes软件包:简短的参考和提示May 08, 2025 am 12:05 AM

Go的bytes包主要用于高效处理字节切片。1)使用bytes.Buffer可以高效进行字符串拼接,避免不必要的内存分配。2)bytes.Equal函数用于快速比较字节切片。3)bytes.Index、bytes.Split和bytes.ReplaceAll函数可用于搜索和操作字节切片,但需注意性能问题。

Go Bytes软件包:字节切片操纵的实例Go Bytes软件包:字节切片操纵的实例May 08, 2025 am 12:01 AM

字节包提供了多种功能来高效处理字节切片。1)使用bytes.Contains检查字节序列。2)用bytes.Split分割字节切片。3)通过bytes.Replace替换字节序列。4)用bytes.Join连接多个字节切片。5)利用bytes.Buffer构建数据。6)结合bytes.Map进行错误处理和数据验证。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境