Maison  >  Article  >  développement back-end  >  Testez les problèmes de gorm à l'aide de go-sqlmock, en comparant les requêtes avec mock.ExpectQuery et regexp.QuoteMeta

Testez les problèmes de gorm à l'aide de go-sqlmock, en comparant les requêtes avec mock.ExpectQuery et regexp.QuoteMeta

WBOY
WBOYavant
2024-02-11 12:48:08405parcourir

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

Pendant le processus de développement, il est courant d'utiliser go-sqlmock pour tester les problèmes de gorm. go-sqlmock est un outil pour simuler les opérations de base de données, tandis que gorm est une bibliothèque ORM populaire en langage Go. Au cours du processus de test, nous devons souvent comparer si l'instruction de requête répond aux attentes. Pour ce faire, nous pouvons utiliser mock.ExpectQuery et regexp.QuoteMeta à des fins de comparaison. Cette méthode peut nous aider à mieux tester et déboguer le code et à garantir l'exactitude et la stabilité du programme. Ensuite, nous présenterons en détail comment utiliser go-sqlmock pour les tests gorm et montrerons comment utiliser mock.ExpectQuery et regexp.QuoteMeta pour comparer les instructions de requête.

Contenu de la question

J'ai un problème pour comparer la requête attendue avec la vraie requête de gorm, voici mon code :

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())
}

Voici le domaine du module :

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"
}

Voici la fonctionnalité que je teste :

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
}

Voici l'erreur que je reçois de la console :

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

Il existe une réponse avec "select(.*)" à la place dans cette section, mais d'après ce que j'ai lu, ce n'est pas une vraie solution

Solution de contournement

Laissez-moi essayer d'aider à résoudre ce problème. J'ai téléchargé tous vos fichiers et domain.gorepository.go me semble bien.
Cependant, j'ai trouvé quelques petits problèmes dans le fichier repository_test.go :

  1. Les backticks manquent dans la requête SQL que vous avez écrite
  2. Supplémentaire ;
  3. en fin de requête
  4. Appel manquant à la withargs(2) méthode

Si vous ajustez ces petites choses, vous devriez vous retrouver avec un code qui ressemble à ceci :

// ... 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())
}

Ensuite, si vous essayez d'exécuter le test, cela devrait fonctionner.
S'il vous plaît laissez-moi savoir si cela résout votre problème, merci !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer