DATA-DOG/go-sqlmock: mocking SQL drivers in Go tests without a database
Sql mock driver for golang to test database interactions
At a glance
- What is it?
- go-sqlmock implements database/sql/driver so tests can assert on queries, arguments and transactions without a real database. It is stable, dependency-free, and deliberately not a SQL parser.
- Who is it for?
- Adopt go-sqlmock if you write Go code against database/sql and want unit tests that assert on exact queries, arguments and transaction boundaries without a database process. Do not adopt it if you need to validate real schema behaviour, dialect-specific SQL, or anything a live engine decides, such as constraint violations; the project itself points to go-txdb for functional testing against a real database.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 83 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem go-sqlmock solves for Go database code
Go's database/sql package hands you a *sql.DB, and most application code takes that pointer directly. That makes the database a hard dependency of every test: without a server, the test fails to connect; with a server, the test needs fixtures, cleanup and a schema that matches production. go-sqlmock removes the server from the equation. It implements the sql/driver interfaces, so a *sql.DB built on it behaves like a normal connection pool from the caller's point of view. The README states the library has one and only purpose: to simulate any sql driver behavior in tests, without needing a real database connection, and that it helps maintain a correct TDD workflow. The audience is Go developers who already write against database/sql and want the query strings, the bound arguments and the transaction calls themselves to be the subject of the test. It does not require any modifications to your source code, which is the part that matters in practice: your repository functions keep taking *sql.DB, and only the test file knows a mock exists.
How expectations, matching and transactions actually work
The mechanism is an ordered queue of expectations. sqlmock.New() returns a *sql.DB, a sqlmock.Sqlmock and an error. Every ExpectBegin, ExpectExec, ExpectQuery, ExpectCommit or ExpectRollback call appends to that queue, and the mock consumes entries as the code under test issues calls. Ordering is strict by default, as the README notes, so a test that commits before it inserts will fail rather than silently pass. Argument matching is value based through WithArgs, with an escape hatch: the Argument interface lets you supply a type whose Match method decides whether a driver.Value is acceptable, which is how the README handles time.Time and similar structs that do not compare cleanly. Query matching is pluggable. By default sqlmock uses QueryMatcherRegexp, which treats the expected SQL string as a regular expression; QueryMatcherEqual does a full case sensitive comparison instead. The README is explicit that sqlmock will not ship standard SQL parsing matchers, because various drivers may not follow the same SQL standard. That is an honest boundary and it shapes how you write tests: a regexp like "UPDATE products" matches the statement, but it does not prove the statement is valid SQL for any particular engine. Column metadata is also mockable, which the v1.5.0 release notes describe as adding column metadata for mocking. The repository layout reflects the version split: expectations_before_go18.go, expectations_go18.go and expectations_go19.go exist so build tags select the right implementation for the toolchain in use.
Installing go-sqlmock and writing a first test
The README gives a single install line. It fetches the module; there is no binary, no server and no configuration file. The module path is github.com/DATA-DOG/go-sqlmock and the repository's go.mod declares go 1.15.
go get github.com/DATA-DOG/go-sqlmockA first test follows the shape the README demonstrates. You open a mock connection, declare the calls you expect in order, run the function under test, then check that every expectation was consumed. The README's own example wraps a recordStats function that begins a transaction, runs an UPDATE and an INSERT, then commits.
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
defer db.Close()
mock.ExpectBegin()
mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()After the code under test runs, the README checks the queue explicitly. This call is what turns a mock into an assertion: without it, a test that never reaches the INSERT still passes.
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("there were unfulfilled expectations: %s", err)
}If you want literal SQL comparison rather than a regular expression, pass the option at construction time. This is the README's example for switching matchers.
db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))Where go-sqlmock stops being the right tool
The mock only knows what you told it. It does not parse SQL, it does not know your schema, and it cannot tell you that a column does not exist or that a foreign key would be violated. A test that passes against go-sqlmock proves your Go code issues the calls you expected; it proves nothing about whether the database accepts them. The README concedes the parsing gap directly, stating that sqlmock will not provide standard sql parsing matchers since drivers may not follow the same SQL standard. There is a second, quieter failure mode in the default matcher. Because QueryMatcherRegexp treats your expected string as a regular expression, characters that are meaningful in regex syntax carry that meaning. A query containing parentheses, a plus sign or a dot can match more than you intended, and a matcher that is too loose will keep passing after the underlying query changes. QueryMatcherEqual is the blunt fix, but it also means any whitespace or casing change in the query breaks the test. Neither matcher understands dialects, so the same expectation cannot distinguish MySQL from Postgres syntax. Finally, the project's own README carries a maintenance note: the author states they do not have much spare time for the library and are willing to transfer the repository ownership to a person or organization motivated to maintain it, pointing at issue #230. The library is described as complete and stable, which cuts both ways: few breaking changes, but also few new features.
go-sqlmock versus go-txdb and other Go testing approaches
The README itself names the alternative it considers complementary: go-txdb, which functionally tests against a real database and isolates all database related actions within a single transaction so the database can remain in the same state. The difference in approach is where the truth lives. go-sqlmock replaces the driver, so the test asserts on the conversation between your code and the driver. go-txdb keeps the real driver and wraps each test in a transaction that is rolled back, so the assertions run against the actual engine and its actual SQL dialect, at the cost of a running database and a connection per test. Neither replaces the other: a repository can use go-sqlmock for fast unit tests of query construction and go-txdb for a smaller set of integration tests. The same trade-off applies against generic mocking tools. A general purpose mock generator produces a fake for an interface you define; go-sqlmock sits one layer lower, at the database/sql/driver boundary, which is why it needs no changes to your source and why it can intercept Begin, Commit and Rollback as first class expectations rather than as method calls on a hand written fake. The cost of that position is that you cannot mock an interface you invented, only the driver behaviour underneath it.
Maintenance, licence and upgrade cost
The repository is not archived, and its last push was on 2026-07-10. The most recent tagged release listed is v1.5.2 from 2024-01-06, following v1.5.1 in December 2023 and v1.5.0 in August 2020, which added column metadata for mocking. That release cadence, combined with the README's statement that the library is now complete and stable, suggests the API is not moving quickly. The open request for a maintainer is the item to weigh if you are planning a multi-year dependency. Upgrade cost is mostly historical rather than ongoing. The README records one breaking change, in v1.2.0, where sqlmock.Rows changed from an interface to a struct; any code holding a type reference to that interface had to switch to a pointer struct type, and the driver.Rows implementation that sqlmock.Rows used to provide was removed. There is also a build tag surface to keep in mind: the repository splits code across files such as expectations_before_go18.go, expectations_go18.go and expectations_go19.go, and the README points to .travis.yml for supported Go versions. The dependency footprint is small. The go.mod file lists a single requirement, github.com/kisielk/sqlstruct, while the README states the library has no third party dependencies. On licensing, the repository carries a LICENSE file and the metadata reports the licence as NOASSERTION, meaning no standard SPDX identifier was detected. Read the LICENSE file in the repository before you rely on it, and treat that as an input to your own legal review rather than something this article can settle.
Editorial conclusion
Adopt go-sqlmock if you write Go code against database/sql and want unit tests that assert on exact queries, arguments and transaction boundaries without a database process. Do not adopt it if you need to validate real schema behaviour, dialect-specific SQL, or anything a live engine decides, such as constraint violations; the project itself points to go-txdb for functional testing against a real database. Before committing, verify three things: that your expectations are written with the default QueryMatcherRegexp in mind, that you call mock.ExpectationsWereMet() in every test, and that your Go version still matches the build tags in the repository, since the code is split across expectations_before_go18.go, expectations_go18.go and expectations_go19.go. The README states the library is complete and stable, and the maintainer is openly looking to transfer the repository, so treat the current API as the API you will keep.
Frequently asked questions
What is go-sqlmock used for?
It is a mock library implementing sql/driver, used to simulate any sql driver behavior in tests without a real database connection, which the README frames as a way to maintain a correct TDD workflow. It requires no modifications to your source code.
How do I install go-sqlmock?
The README gives one command: go get github.com/DATA-DOG/go-sqlmock. There is no binary or service to run; the module path is github.com/DATA-DOG/go-sqlmock.
Does go-sqlmock work with Postgres or MySQL specific SQL?
The README states sqlmock will not provide standard sql parsing matchers, since various drivers may not follow the same SQL standard, so matching is done on the expected string rather than by parsing a dialect. The README's own example is written against the go-mysql-driver.
What is SQL query test?
In go-sqlmock the query string is matched against an expectation, either as a regular expression through the default QueryMatcherRegexp or as a full case sensitive match through QueryMatcherEqual. The mock checks that the expected calls occurred in order, not that the SQL is valid for a database engine.
What database to use with Go?
go-sqlmock does not answer that question, because it replaces the driver rather than connecting to an engine. The README points to go-txdb for functionally testing with a real database, where all database related actions are isolated within a single transaction.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/data-dog-go-sqlmock)