Home  >  Article  >  Backend Development  >  Gorm delete clause sqlmock test

Gorm delete clause sqlmock test

WBOY
WBOYforward
2024-02-08 22:30:31816browse

Gorm 删除子句 sqlmock 测试

php editor Xinyi introduces to you the Gorm delete clause sqlmock test. Gorm is an excellent ORM framework in the Go language, and sqlmock is a testing tool for Gorm, used to simulate database operations. When developing Gorm, we often need to test the database deletion operation. At this time, we can use sqlmock to simulate the database deletion operation for unit testing and integration testing. This article will introduce you in detail how to use Gorm and sqlmock to test delete clauses, helping you better carry out database-related development work.

Question content

I have a gorm deleted and the result is returned:

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)

Tests with clauses now always fail. For example:

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

Receive error:

'Calling query 'delete from "my_users" where created_at < $1 returning "email"' with parameters [{name: ordinal:1 value:2023-01-18 06:15:34.694274 0000 utc}] is not expected , the next expectation is: expectedexec => expected exec or execcontext where:\n - matches sql: 'delete'\n - with parameters:\n 0 - 2023-01-18 06:15:34.694274 0000 utc\n - should return results with:\n lastinsertid: 1\n rowsaffected: 1"

I tried many other sqlmock expectations but they had similar issues. Also, we have no return value in expectexec, only in expectquery... Does anyone have to test gorm queries with clauses?

SOLUTION

I was able to successfully manage your needs. First, let me share the file I wrote, and then I'll walk you through all the relevant changes. These files are repo.go for production and repo_test.go for test code.

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
}

Since you didn't provide the complete file, I tried to guess what is missing.

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

Here are more changes worth mentioning:

  1. I instantiated anytime according to the documentation (you can see the link in the comments).
  2. I'm second guessing the settings for db, mock and gormdb, but I think they should be roughly the same.
  3. I switched the usage of expectexec to expectquery because we will return the results specified by the repo.go method in the clauses file set.
  4. You must wrap expectquery in expectbegin and expectcommit.
  5. Finally, note the differences in how drivers expect parameters in sql statements. In production code, you can choose to use ? or $1. But in the test code, you can only use ?, otherwise it will not meet expectations.

Hope it can be of some help, otherwise please let me know!

The above is the detailed content of Gorm delete clause sqlmock test. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete