Maison  >  Article  >  développement back-end  >  Test sqlmock de la clause de suppression Gorm

Test sqlmock de la clause de suppression Gorm

WBOY
WBOYavant
2024-02-08 22:30:31817parcourir

Gorm 删除子句 sqlmock 测试

L'éditeur PHP Xinyi vous présente le test sqlmock de la clause de suppression Gorm. Gorm est un excellent framework ORM dans le langage Go, et sqlmock est un outil de test pour Gorm, utilisé pour simuler les opérations de base de données. Lors du développement de Gorm, nous devons souvent tester l'opération de suppression de base de données. À ce stade, nous pouvons utiliser sqlmock pour simuler l'opération de suppression de base de données pour les tests unitaires et les tests d'intégration. Cet article vous présentera en détail comment utiliser Gorm et sqlmock pour tester les clauses de suppression, vous aidant ainsi à mieux effectuer les travaux de développement liés aux bases de données.

Contenu de la question

J'ai une suppression de gorm, le résultat renvoyé est :

expirationdate := time.now().utc().add(-(48 * time.hour))
var deletedusers users
res := gormdb.withcontext(ctx).
    table("my_users").
    clauses(clause.returning{columns: []clause.column{{name: "email"}}}).
    where("created_at < ?", expirationdate).
    delete(&deletedusers)

Les tests avec des clauses échouent désormais toujours. Par exemple :

sqlMock.ExpectExec(`DELETE`)
    .WithArgs(expirationDate)
    .WillReturnResult(sqlmock.NewResult(1, 1))

Erreur de réception :

"L'appel de la requête 'supprimer de "mes_utilisateurs" où créé_at < $1 renvoyant "email"' avec les paramètres [{name : ordinal:1 value:2023-01-18 06:15:34.694274 +0000 utc}] n'est pas attendu, L'attente suivante est : attenduexec => ; attend exec ou execcontext où : n - correspond à sql : 'delete'n - prend les arguments : n 0 - 2023-01-18 06:15:34.694274 +0000 utc n - devrait renvoyer avec les résultats pour : n lastinsertid : 1n lignes affectées : 1"

J'ai essayé de nombreuses autres attentes sqlmock mais elles avaient des problèmes similaires. De plus, nous n'avons aucune valeur de retour dans expectexec, uniquement dans expectquery... Quelqu'un doit-il tester les requêtes gorm avec des clauses ?

Solution

J'ai su gérer avec succès vos besoins. Tout d'abord, permettez-moi de partager le fichier que j'ai écrit, puis je vous expliquerai toutes les modifications pertinentes. Ces fichiers sont destinés à une utilisation en production repo.go 和用于测试代码的 repo_test.go.

repo.go

package gormdelete

import (
    "context"
    "time"

    "gorm.io/gorm"
    "gorm.io/gorm/clause"
)

type users struct {
    email string
}

func delete(ctx context.context, gormdb *gorm.db) error {
    expirationdate := time.now().utc().add(-(48 * time.hour))

    var deletedusers users
    res := gormdb.withcontext(ctx).table("my_users").clauses(clause.returning{columns: []clause.column{{name: "email"}}}).where("created_at < ?", expirationdate).delete(&deletedusers)
    if res.error != nil {
        return res.error
    }
    return nil
}

Comme vous n'avez pas fourni le dossier complet, j'ai essayé de deviner ce qui manque.

repo_test.go

package gormdelete

import (
    "context"
    "database/sql/driver"
    "testing"
    "time"

    "github.com/DATA-DOG/go-sqlmock"
    "github.com/stretchr/testify/assert"
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

// this is taken directly from the docs
// https://github.com/DATA-DOG/go-sqlmock#matching-arguments-like-timetime
type AnyTime struct{}

// Match satisfies sqlmock.Argument interface
func (a AnyTime) Match(v driver.Value) bool {
    _, ok := v.(time.Time)
    return ok
}

func TestDelete(t *testing.T) {
    db, mock, err := sqlmock.New()
    if err != nil {
        t.Fatalf("an error was not expected: %v", err)
    }

    conn, _ := db.Conn(context.Background())
    gormDb, err := gorm.Open(postgres.New(postgres.Config{
        Conn: conn,
    }))

    row := sqlmock.NewRows([]string{"email"}).AddRow("<a href="https://www.php.cn/link/89fee0513b6668e555959f5dc23238e9" class="__cf_email__" data-cfemail="9febfaecebdffae7fef2eff3fab1fcf0f2">[email&#160;protected]</a>")
    mock.ExpectBegin()
    mock.ExpectQuery("DELETE FROM \"my_users\" WHERE created_at < ?").WithArgs(AnyTime{}).WillReturnRows(row)
    mock.ExpectCommit()

    err = Delete(context.Background(), gormDb)

    assert.Nil(t, err)
    if err = mock.ExpectationsWereMet(); err != nil {
        t.Errorf("not all expectations were met: %v", err)
    }
}

Voici d'autres changements qui méritent d'être mentionnés :

  1. J'ai instancié anytime selon la documentation (vous pouvez voir le lien dans les commentaires).
  2. J'ai deviné les paramètres pour dbmockgormdb mais je pense qu'ils devraient être à peu près les mêmes.
  3. J'ai changé l'utilisation de expectexec en expectquery car nous renverrons l'ensemble de résultats spécifié par la méthode expectexec 的用法切换为 expectquery,因为我们将返回 clauses 文件中 repo.go dans le fichier clauses.
  4. Vous devez mettre expectquery 包装在 expectbeginexpectcommit dedans.
  5. Enfin, notez la différence dans la façon dont les pilotes attendent les paramètres dans les instructions SQL. Dans le code de production, vous avez la possibilité d'utiliser ?。但在测试代码中,只能使用?, sinon il ne se comporte pas comme prévu.

J'espère que cela vous aidera, sinon faites-le-moi savoir !

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