如何测试 defer 是否被调用

问题描述 投票:0回答:1

我有以下代码

func (s *MyRepo) InsertOrder(ctx context.Context, orderID string) error {
    query := `INSERT INTO orders (orderID) VALUES (?)`

    stmt, err := s.db.RawDatabase().PrepareContext(ctx, query)
    if err != nil {
        return err
    }
    defer stmt.Close()

    _, err = stmt.ExecContext(ctx, orderID)
    if err != nil {
        //log err
    }
    return err
}

对应的测试用例是

func TestMyRepo_InsertOrder_Success(t *testing.T) {
    orderID := "orderID"
    mockDB, repo := getDBStore()
    query := `[INSERT INTO orders (orderID) VALUES (?)]`
    mockDB.ExpectPrepare(query).
        ExpectExec().
        WithArgs(orderID).
        WillReturnResult(sqlmock.NewResult(1, 1)).
        WillReturnError(nil)

    err := repo.InsertOrder(context.Background(), orderID)
    assert.Nil(t, err)
}

但这并不会测试

defer stmt.Close()
是否已被调用(一旦函数结束就会被调用)。我该如何测试这个?

unit-testing go mocking defer-keyword
1个回答
1
投票

看起来您正在使用 data-dog 的 sqlmock 包,因此您应该能够使用

ExpectClose()
来注册数据库将关闭的期望,并使用
ExpectationsWereMet()
来收集此信息。

如果您使用其他软件包,请随意链接;可能有类似的东西可用,最坏的情况是你可以在他们的包装器周围编写你自己的包装器。当开发人员使用模拟编写测试时,确保调用特定依赖项的特定方法是一个相当普遍的愿望,因此大多数更好的模拟包都会不遗余力地提供某种 API 来检查这一点。

正如对此问题的评论中所指出的,这种性质的测试通常具有一些值得怀疑的价值,并且它们的存在似乎更多是为了增加诸如代码覆盖率百分比之类的可疑指标,而不是为了提高代码可靠性或可维护性。

© www.soinside.com 2019 - 2024. All rights reserved.