Gorm delete clause sqlmock test

WBOY
Release: 2024-02-08 22:30:31
forward
817 people have browsed it

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)
Copy after login

Tests with clauses now always fail. For example:

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

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
}
Copy after login

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)
    }
}
Copy after login

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!

Related labels:
source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!