---
title: Interface With Your Database in Go Tests
teaser: |
  Go's interface provides a way to abstract away things like your database for
  testing.
tags: web,go,testing
author: Caleb Hearth
published_on: 2015-07-10
---

Go's strong type system
includes a concept called [interface].
In Go,
an interface is a collection of
function signatures.
Any type that implements
all of those functions
is implicitly able to be used
as an interface type.

[interface]: https://gobyexample.com/interfaces

For example,
Go's empty interface, `interface{}`,
is similar to Ruby's `BasicObject` or Java's `Object`,
from which all classes inherit in these languages.

More concretely,
Ruby's `Comparable` requires a `#<=>` method to be defined.
To represent that in Go,
we might define these interfaces as:

```go
type Comparable interface {
  // Compare accepts another Comparable of the same type and returns an int
  // value representing whether the other is less than (-1), greater than (1),
  // or equal to (0) the callee.
  // Compare returns an error if the Comparable argument is of a different type
  // than the callee and cannot be compared.
  Compare(Comparable) (int, error)
}

```

We could then use any type that implemented `Comparable` in methods defined to
operate on `Comparable`:

```go
func (self int) Compare(other Comparable) (int, error) {
  switch other.(type) {
  case int:
  case float64:
    other = int(other)
  case string:
    other, err = strconv.Atoi(other)
    if err != nil {
      return 0, err
    }
  default:
    return 0, fmt.Errorf("%v is not comparable to type int.")
  }

  if other > self {
    return 1, nil
  } else if other == self {
    return 0, nil
  } else {
    return -1, nil
  }
}

func Equal(first, second Comparable) (bool, err) {
  if result, err := first.Compare(second); err != nil {
    return false, err
  }

  return result == 0, nil
}

```

Okay, that's out of the way.
Now let's look at how we can use interfaces
to abstract away a database in tests.

We'll define a `DataAccessLayer` interface
which includes signatures for the methods we'll
need:

```go
type DataAccessLayer interface {
  FindAuthor(int) Author
  FindPostsForAuthor(Author) []Post
  FindCommentsForPost(Post) []Comment
}
```

Building to that interface,
we'd define a type `postgres` that included code
to retreive each object or collection from a
database connection it maintains internally.

But for our unit tests,
we don't want to ever touch the database.
By the power of `interface`,
we can define a dummy `TestDAL`
that returns known values so that we can test
`DataAccessLayer`'s collaborators in relative isolation.

```go
type TestDAL {
  Author   Author
  Posts    []Post
  Comments []Comment
}

func (t *TestDAL) FindAuthor(int) Author {
  return t.Author
}

func (t *TestDAL) FindPostsForAuthor(Author) []Post {
  return t.Posts
}

func (t *TestDAL) FindCommentsForPost(Post) []Comment {
  return t.Comments
}
```

We ignore the arguments because we initialize
the `TestDAL` with the result we want,
so they're not needed.

In our test,
we can create just the amount of data we need:

```go
func TestDALCollaborator(t *testing.T) {
  dal := TestDAL{Author: Author{}}
  collaborator := Collaborator{DAL: dal}

  result := collaborator.FunctionNeedingAnAuthor()

  // Some verification
}
```

And we never need to hit an external dependency
like the Postgres database
in our test,
keeping it blazing fast.
