I\'m trying to write tests for some code using Gorm using sqlmock. I figured out writing tests for my insert function but now pulling my hair out trying to get an update wor
mock.ExpectExec()
function does not perform simple strings comparison. Instead it uses input string as RegExp to match the query.
Some characters in your SQL match string are reserved RegExp characters and should be escaped to match SQL.
Your string should look like this after escaping:
SELECT \* FROM "storage_pools" WHERE "storage_pools"\."deleted_at" IS NULL AND \(\(poolid \= \?\)\) ORDER BY "storage_pools"\."id" ASC LIMIT 1
Hint: You can escape your string online using https://www.regex-escape.com/preg_quote-online.php or some other site
Additional thought: Test with exact SQL match can be fragile without adding much extra value for exact SQL.
Test can give you false positive result if anyone made harmless change in it like adding extra space character. From other side, full text match does not catch DB schema changes that are not compatible with SQL.
I ended up with this setup for my projects:
Run unit tests with mock.ExpectExec()
with basic substrings like INSERT INTO history
. That makes tests much less fragile. At the same time we are still checking a lot in this test to verify code execution flow:
On top of that we have to run integration tests for our SQL queries. That is the only way to make sure that our SQL are correct and up to date with latest DB changes.
P.S. Avoid *
in select. Be explicit with field names.
Update1:
Be careful with strings case. "SELECT" and "select" are two different strings.
Some code snippets from my current project:
// insert
sqlMock.ExpectExec("INSERT INTO eeo").
WithArgs("2018-12-31", "John Dow", "title"}).
WillReturnResult(sqlmock.NewResult(mock.EeoID, 1))
// select
rows := sqlmock.NewRows([]string{"req_id", "state"})
sqlMock.ExpectQuery("select").WithArgs(mock.CandidateID).WillReturnRows(rows)