Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gorm.DB mocking for Unit Testing #1525

smikulcik opened this issue Jul 6, 2017 · 5 comments


Copy link

commented Jul 6, 2017

I would like to be able to use for unit testing my gorm DB instance. However, gorm.DB is a struct and its methods return pointers to the struct. For testify/mock, we need methods to work on interfaces. For instance, gorm.DB.Find must return an interface, not a struct pointer for mocking to work.

What version of Go are you using (go version)?

go version go1.8.3 darwin/amd64

Which database and its version are you using?

sqlite 3.16.0 2016-11-04 19:09:39 0e5ffd9123d6d2d2b8f3701e8a73cc98a3a7ff5f

What did you do?

Here I have a simple database program that has one model, Item, and one database dependent method. I'd like to unit test GetItems(), but I need to mock out the database instance to do that.


package main

import (
	_ ""

type Item struct {
	Name string

func setupDB() *gorm.DB {
	db, err := gorm.Open("sqlite3", "test.db")
	if err != nil {
		panic("failed to connect database")

	return db

// GetItems Function that I want to test
func GetItems(db IDatabase) []*Item {
	var items []*Item
	return items

// IDatabase database interface for mocking
type IDatabase interface {
	Find(out interface{}, where ...interface{}) IDatabase

func main() {
	db := setupDB()
	defer db.Close()


package main

import (


// MockDatabase mock database for testing
type MockDatabase struct {

// Find find
func (m *MockDatabase) Find(out interface{}, where ...interface{}) IDatabase {
	args := m.Called(out, where)
	return args.Get(0).(IDatabase)

// TestGetItems test function
func TestGetItems(t *testing.T) {
	m := &MockDatabase{}

	m.On("Find", mock.Anything, mock.Anything).Return(m)



The tests run fine and pass, but when I try to run the main file, it fails.

$ go run main.go 
# command-line-arguments
./main.go:38: cannot use db (type *gorm.DB) as type IDatabase in argument to GetItems:
	*gorm.DB does not implement IDatabase (wrong type for Find method)
		have Find(interface {}, ...interface {}) *gorm.DB
		want Find(interface {}, ...interface {}) IDatabase

This comment has been minimized.

Copy link

commented Jul 9, 2017

Because go's type system is not covariant\contrvariant. Find(interface {}, ...interface {}) *gorm.DB is not Find(interface {}, ...interface {}) IDatabase, even if *gorm.DB implemented IDatabase interface.


This comment has been minimized.

Copy link

commented Sep 1, 2017

i will find a tdd solution for gorm now. and i think we need a mock sql.Database implemention ?


This comment has been minimized.

Copy link

commented Sep 9, 2017

@smikulcik @mykytanikitenko @imiskolee @sunfmin @levinalex
I use sqlmock to mock-test GORM queries. Example is here, search e.g. testUserSelectAll.
First I tried go-testdb and custom gorm.DB wrapper to interface, but current solution with sqlmock is the simplest.


This comment has been minimized.

Copy link

commented Feb 12, 2018

Refer #1424

@jinzhu jinzhu closed this Feb 12, 2018


This comment has been minimized.

Copy link

commented Mar 26, 2018

👍 for adding a db mock for use in (Unit) tests. Would something like gorm.Open("test", ... (or mock) make any sense?

Anyway, currently, as others stated, mocks can be implemented with like:

import (
func TestMyGoodness(t *testing.T) {
  db, mock, _ := sqlmock.New()
  models.Db, _ = gorm.Open("postgres", db)
  sqlRows := sqlmock.NewRows([]string{"details"}).
    AddRow(`{"name": "foo", "type": "bar", ... }`
  mock.ExpectQuery("^SELECT (.+) FROM \"products\" (.+)$").WillReturnRows(sqlRows)
// some http request recording or other operations
// and then the usual expected := , if ... != t.Errorf combo:
expected := `{"products":[{"details":{"name": "foo", "type": "bar"}}]}`

The above assumes that *gorm.DB is used/initialized like so:

package models

var Db *gorm.DB

// somewhere else:
scope := models.Db.Select("id, details, created_at, updated_at")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
6 participants
You can’t perform that action at this time.