Recently, I was trying to query data with preload function that gorm provided.
Here's the actual implementation looks like:
func (repo *SectorRepository) GetSectorsByStockCode(stockCode string) *model.Sector {
var foundStocks []*model.Stock
repo.DB.Where("code = ?", stockCode).Preload("Sectors").Find(&foundStocks)
if foundStocks == nil {
return nil
} else if len(foundStocks) == 0 {
return nil
} else if foundStocks[0].Sectors == nil {
return nil
} else if len(foundStocks[0].Sectors) == 0 {
return nil
} else {
return foundStocks[0].Sectors[0]
}
}
Then this is what I've done on my unit test:
func Test_SectorRepo_GetSectorsByStockCode(t *testing.T) {
db, gdb, sqlMock, err := InitTestSectorRepo()
require.NoError(t, err)
defer db.Close()
repository := repository.SectorRepository{DB: gdb}
var stockCode = "AAPL"
var expectedCode = "code1"
var expectedName = "name1"
var exchangeCode = "exchange_code1"
var sectorCode = "sector_code1"
var now = time.Now()
sqlMock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "stocks" WHERE code = $1`)).WithArgs(stockCode).WillReturnRows(
sqlMock.NewRows([]string{"code", "name", "exchange_code", "created_at", "updated_at"}).
AddRow(expectedCode, expectedName, exchangeCode, now, now),
)
sqlMock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "stock_sectors" WHERE ("stock_sectors"."stock_code","stock_sectors"."stock_exchange_code") IN (($1,$2))`)).
WithArgs(expectedCode, exchangeCode).WillReturnRows(sqlMock.NewRows([]string{"stock_code", "stock_exchange_code", "sector_code"}).AddRow(expectedCode, exchangeCode, sectorCode))
sqlMock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "sectors" WHERE "sectors"."code" = $1'`)).WithArgs(stockCode).WillReturnRows(
sqlMock.NewRows([]string{"code", "name", "created_at", "updated_at"}).AddRow(sectorCode, "sector_name1", now, now),
)
res := repository.GetSectorsByStockCode(stockCode)
require.Equal(t, res.Name, expectedName)
}
But I got a failing message as provided below:
Running tool: /usr/local/go/bin/go test -timeout 30s -run ^Test_SectorRepo_GetSectorsByStockCode$ gitlab.com/xxx/yyy-service/test/repository
2022/07/02 20:38:10 [32m/Users/aaa/yyy-service/api/repository/sector_repository.go:38
[0m[33m[0.045ms] [34;1m[rows:1][0m SELECT * FROM "stock_sectors" WHERE ("stock_sectors"."stock_code","stock_sectors"."stock_exchange_code") IN (('code1','exchange_code1'))
2022/07/02 20:38:10 [31;1m/Users/aaa/yyy-service/api/repository/sector_repository.go:38 [35;1mQuery: could not match actual sql: "SELECT * FROM "sectors" WHERE "sectors"."code" = $1" with expected regexp "SELECT \* FROM "sectors" WHERE "sectors"\."code" = \$1'"
[0m[33m[0.025ms] [34;1m[rows:0][0m SELECT * FROM "sectors" WHERE "sectors"."code" = 'sector_code1'
2022/07/02 20:38:10 [31;1m/Users/aaa/yyy-service/api/repository/sector_repository.go:38 [35;1mQuery: could not match actual sql: "SELECT * FROM "sectors" WHERE "sectors"."code" = $1" with expected regexp "SELECT \* FROM "sectors" WHERE "sectors"\."code" = \$1'"
[0m[33m[1.300ms] [34;1m[rows:1][0m SELECT * FROM "stocks" WHERE code = 'AAPL'
--- FAIL: Test_SectorRepo_GetSectorsByStockCode (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x14499f6]
goroutine 4 [running]:
testing.tRunner.func1.2({0x1497620, 0x1896c40})
/usr/local/go/src/testing/testing.go:1209 +0x24e
testing.tRunner.func1()
/usr/local/go/src/testing/testing.go:1212 +0x218
panic({0x1497620, 0x1896c40})
/usr/local/go/src/runtime/panic.go:1038 +0x215
gitlab.com/xxx/yyy-service/test/repository_test.Test_SectorRepo_GetSectorsByStockCode(0x0)
/Users/aaa/yyy-service/test/repository/sector_repository_test.go:131 +0x8b6
testing.tRunner(0xc00011b380, 0x1526fd8)
/usr/local/go/src/testing/testing.go:1259 +0x102
created by testing.(*T).Run
/usr/local/go/src/testing/testing.go:1306 +0x35a
FAIL gitlab.com/xxx/yyy-service/test/repository 0.533s
FAIL
I thought in the first place that gorm preload function will create subsequent queries, hence I on the above code I was trying to evaluate all the subsequent queries.
Until now I'm still figuring it out if it's possible to test the preload gorm query by using sqlmock.
If there's anyone who could help to answer this problem will be much appreciated :)