2

I have this code in my application, I use goroutine because that queries are very slow. The code works correctly but I've been trying to test that function with sqlmock and that been having a lot of false positives and a lot of dificulties, what can I do to test those queries using sqlmock? (Obs: I've used postgres)

func(r repository) Queries(ctx context.Context) (*models.MyModel, error) {
    var users int64
    var services int64
    var sells int64

    queryReponses := make(chan *gorm.DB, 3)

    go func(){
        queryResponses <- r.db.Raw("SELECT COUNT(*) FROM deposits").Find(&users)
    }()
    go func(){
        queryResponses <- r.db.Raw("SELECT COUNT(*) FROM services").Find(&users)
    }()
    go func(){
        queryResponses <- r.db.Raw("SELECT COUNT(*) FROM sells").Find(&users)
    }()

    for i := 0; i < 3; i += 1 {
        queryResponse := <-queryReponses
        if queryResponse.Error != nil {
            return &models.MyModel{}, fmt.Errorf(queryResponse.Error)
        }
    }

    return &models.MyModel{
        Users: users,
        Services: services,
        Sells: sells,
    }
}
  • You can make the goroutine functions non-anonymous or wrap each query into its own function and test them aside by simply calling them, etc. It really depends what you want to test (that you got query right?). Also you seem to have `Find()` arguments wrong in second and third anonymous function. – blami Sep 20 '22 at 12:41

1 Answers1

0

You modify the same value concurrently, run your tests with a -race detector flag to detect it

 go func(){
        queryResponses <- r.db.Raw("SELECT COUNT(*) FROM deposits").Find(&users)
    }()
-    go func(){
        queryResponses <- r.db.Raw("SELECT COUNT(*) FROM services").Find(&users)
+    go func(){
        queryResponses <- r.db.Raw("SELECT COUNT(*) FROM services").Find(&services)
    }()
-    go func(){
        queryResponses <- r.db.Raw("SELECT COUNT(*) FROM sells").Find(&users)
    }()
+    go func(){
        queryResponses <- r.db.Raw("SELECT COUNT(*) FROM sells").Find(&sells)
    }()

also for such a case the sync/errgroup is more convenient to use:

var g errgroup.Group

g.Go(func() error {
    return r.db.Raw("SELECT COUNT(*) FROM deposits").Find(&users).Error
})
g.Go(func() error {
    return r.db.Raw("SELECT COUNT(*) FROM services").Find(&services).Error
})

if err := g.Wait(); err == nil {
  return &models.MyModel{}, fmt.Errorf(queryResponse.Error)
}
slsy
  • 1,257
  • 8
  • 21