【问题标题】:How to mock a ping command如何模拟 ping 命令
【发布时间】:2020-01-19 12:59:46
【问题描述】:

我正在使用https://github.com/DATA-DOG/go-sqlmock 并尝试模拟与数据库的连接。

现在,我需要模拟一个 ping 命令(出于负载平衡目的)。但是,我找不到有关如何执行此操作的任何信息。

例如,我想写一个这样的测试

    db, mock, _ := sqlmock.New()    
    // ExpectPing does not exist, but it is there anything similar?
    mock.ExpectPing().WillReturnError("mock error")

    err := db.Ping()
    if err==nil{
    t.Fatal("there should have been an error")
    }

此外,我需要将这个模拟对象注入到一个函数中。假设 New(*sql.DB) 输出一个新结构。所以它必须与 *sql.DB 结构兼容。出于这个原因,sqlmock 似乎是一个不错的选择。但是,我还没有找到模拟 ping 命令的方法。

有没有办法使用这个库来做到这一点? 如果没有,是否有任何其他数据库/sql 模拟库可以做到这一点?

【问题讨论】:

  • 一种选择是 fork go-sqlmock repo 并自己添加 ExpectPing

标签: database go mocking


【解决方案1】:

更新:自 2020 年 1 月 6 日起,此功能将 has been added 更改为 go-sqlmock,并包含在 v1.4.0 release 中。


原答案:

不,没有“相似之处”。 PingPingContext 方法依赖于实现 Pinger 接口的驱动程序,因此您不能通过例如期待 'SELECT 1' 或其他东西来模仿它。

already an issue 请求添加此内容。似乎没有引起太多关注。我怀疑创建一个 PR(大约 3 行代码)会大大增加添加该功能的机会。


如果您的目标是让 Ping 失败,您应该能够通过连接到无效的数据库端点(使用或不使用 sqlmock)来模仿它。

【讨论】:

    【解决方案2】:

    你当然可以模拟 db 本身:

    type mockedDB struct {
        *sql.DB
    }
    
    func (db *mockedDB) Ping() error {
        return errors.New("not implemented")
    }
    
    func Example_mockedDB_Ping() {
        db, _, _ := sqlmock.New()
        defer db.Close()
    
        mdb := mockedDB{db}
        fmt.Println("mdb.Ping(): ", mdb.Ping())
        // Output: mdb.Ping():  not implemented
    }
    

    但我不明白这种实验的目的是什么。

    同样的方法你可以把mock放到一个新的类型中,然后在上面定义ExpectPing

    【讨论】:

    • 不错的答案。但我需要通过函数将模拟对象注入另一个对象:New(*sql.DB)。恰好只接受 *sql.DB 类型。所以这种模拟的想法不适用。我已经相应地更新了我的问题
    【解决方案3】:

    我还需要模拟 Ping() 功能。我就是这样解决的:

    type mockDB struct {
        ReturnError error
    }
    
    func (db *mockDB) Ping() error {
        return db.ReturnError
    }
    
    func (db *mockDB) PingContext(ctx context.Context) error {
        return db.ReturnError
    }
    
    // Pinger to be able to mock & ask just for a ping
    type Pinger interface {
        PingContext(ctx context.Context) error
        Ping() error
    }
    
    // DatabasePingCheck returns a Check that validates connectivity to a database/sql.DB using Ping().
    func DatabasePingCheck(pinger Pinger, timeout time.Duration) Check {
        return func() error {
            ctx, cancel := context.WithTimeout(context.Background(), timeout)
            defer cancel()
            if pinger == nil {
                return fmt.Errorf("pinger is nil")
            }
            return pinger.PingContext(ctx)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-12-23
      • 1970-01-01
      • 2020-12-04
      • 1970-01-01
      • 2020-10-13
      • 1970-01-01
      • 2016-06-21
      • 2021-01-13
      • 1970-01-01
      相关资源
      最近更新 更多