如何将sqlmock存根以永不返回错误?

时间:2017-11-08 13:10:30

标签: sql database testing go mocking

我无法测试任意使用数据库的函数NewDao。我想检查返回的Dao是否既没有客户也没有零产品。

type Dao struct {
  client ClientDao
  product ProductDao
}

func (d *Dao) Client() ClientDao {
  return d.client
}

func (d *Dao) Product() ProductDao {
  return d.product
}

func NewDao(db *sql.DB) (*Dao, error) {
  if db == nil {
    return nil, errors.New("Can't create a dao from nil database")
  }
  client, err := newClientDao(db) // Uses db arbitrarily
  if err != nil {
    return nil, err
  }
  product, err := newProductDao(db) // Uses db arbitrarily
  if err != nil {
    return nil, err
  }
  return &Dao{client, product}, nil
}

我使用sqlmock测试NewDao(),但它总是失败,因为我不知道mock需要什么。

func TestNewDao(t *testing.T) {
  db, mock, err := sqlmock.New()
  if err != nil {
    t.Fatal("Can't create database for test dao")
  }

  // How to set mock to expect anything and never fail?
  // mock.ExpectQuery(any) ?

  dao, err := NewDao(db)

  // err is never nil, because mock has no expectations

  if err != nil {
    t.Fatal("Can't create dao for test dao.User %q", err)
  }
  if dao.User() == nil {
    t.Fatalf("User dao is nil")
  }
  if dao.Client() == nil {
    t.Fatalf("Client dao is nil")
  }
}

有没有人知道如何存根sqlmock以实现我的目的?或者可以指定sqlmock lib的替代方法吗?

2 个答案:

答案 0 :(得分:1)

您在NewDao的最后一次回复中缺少第二项:

return &Dao{client, product}

应该是:

return &Dao{client, product}, nil

返回语句必须“返回”函数头中声明的所有内容。

答案 1 :(得分:0)

您的Dao.ClientDao.Product方法本身不会调用任何依赖项,因此您无需进行模拟。使用模拟来测试这两种方法毫无意义。

虽然测试这样的一个衬里可能不是最明智的做法,但是如果你想要测试它们,你只需要确保它们返回的值等于它们应该的字段的值。返回。

func TestDaoClient(t *testing.T) {
    var client ClientDao // TODO: prepare a client dao value for test

    tests := []struct{
        name string
        dao *Dao
        want ClientDao
    }{{
        name: "should return client dao",
        dao: &Dao{client: client},
        want: client,
    }, {
        name: "should return nil",
        dao: &Dao{client: nil},
        want: nil,
    }}

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            if got := tt.dao.Client(); !reflect.DeepEqual(got, tt.want) {
                t.Errorf("client got=%v, want=%v", got, tt.want)
            }
        })    
    }
}

现在,您可以对Dao.Product方法执行相同操作。