0

I built the following 2 interfaces in order to make my code, which makes calls to the sql package, testable:

type Database interface {
    Close() error
    Query(string, ...interface{}) (DatabaseRows, error)
}

type DatabaseRows interface {
    Close() error
    Next() bool
    Scan(...interface{}) error
}

and the actual code which I want to test is:

func getDatabase(connectionString string) (db Database, err error) {
    if db , err = sql.Open("mysql", connectionString); err != nil {
        glog.V(0).Infof("Error %s", err)
    }
    return
}

But this fails to compile:

*sql.DB does not implement Database (wrong type for Query method)

have Query(string, ...interface {}) (*sql.Rows, error)

want Query(string, ...interface {}) (DatabaseRows, error)

If I understand it correctly, it's telling me that it can't return a *Row where a DatabaseRow is expected, even though Rows struct in is implementing all 3 functions that I declared in DatabaseRows interface.

Why doesn't compiler make that association?

4
  • 2
    Yes, *sql.Rows does implement DatabaseRows. The problem is that the method signatures are different, resulting in different method sets. Commented Dec 14, 2016 at 23:46
  • I don't follow. I copied Query func's signature from the source. Even looking at the error message, one could see that the only difference between the 2 signature is the return value. Commented Dec 14, 2016 at 23:50
  • 1
    That is the only difference, but there can't be any difference, or it's a different signature. Commented Dec 14, 2016 at 23:52
  • Duh! You'd think that's obvious. Thanks. Commented Dec 15, 2016 at 0:00

1 Answer 1

0

If you haven't found a way to work around this, yet, I would recommend creating a new API around your DB calls which actually return what you want. This means you'll need to apply some judgment, but your tests will end up being cleaner after you apply a little bit of thought to your problem.

For instance, if your DB contains a table like this

+------------+----------+-----+-------------------+
| EmployeeID | Name     | Age | Salary            |
+------------+----------+-----+-------------------+
| 123        | Kara Bob | 28  | 1 Million Dollars |
+ ...

Create an interface like this

type Employee interface {
    GetEmployeeId() int
    GetName() string
    ...
}

Then create a real version calling your SQL database, and then a fake one with struct fields for your tests.

Sign up to request clarification or add additional context in comments.

1 Comment

I created the interfaces the same way I mentioned in my question, but created types that implemented those interfaces and wrapped the actual "database/sql" library's types. That way, I could create (or use other's) test types.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.