Skip to content

Instantly share code, notes, and snippets.

@j16r
Last active June 26, 2019 22:48
Show Gist options
  • Save j16r/6ac2869f4386b209f73af11a696c5c62 to your computer and use it in GitHub Desktop.
Save j16r/6ac2869f4386b209f73af11a696c5c62 to your computer and use it in GitHub Desktop.

This is a quick sketch of how I think terminology applies to the various kinds of mocking and test doubles that apply in Go.

In practice, the most effective way to mock things in Go is to use an interface, and then to substitute a specialized testing implementation in place of a real one. Wherever a substitute is used, I think this should be called a "double".

There is one specialization of a "double" and that is a "fake" implementation. Fakes can often have real world uses, e.g: "RamDiskDatabase", but are typically substituted in order to get real world behavior with some cost eliminated.

Otherwise, all other terminology applies to methods.

A full example

type Vehicle interface {
  func Drive(int distance) error
  func Refuel(int amount) error
  func Accelerate() error
  func Stop() error
}

// A real implementatiom
type Car struct {
  ...
}

// A double which is a fake
type CarWithNoGasConsumption struct {
}

func (c *CarWithNoGasConsumption) Refuel(int amount) error {
  // no-op
  return nil
}

... more impl

// A double which has a mix of mocks/stubs/spies and proxies
type CarDouble struct {
  realCar *Car
  accelCount int
  mocker MockImpl
}

// A stub
func (c *CarDouble) Refuel(int amount) error {
  throw "Refuelling this car is an exception"
}

// A spy
func (c *CarDouble) Accelerate(int amount) error {
  // Record some information about the call
  accelCount += 1
  // TODO: Forward to real impl?
  return nil
}

// A mock
func (c *CarDouble) Stop() error {
  // Record call, test must later make sure all expected calls were made
  c.mocker.RecordExpectedCall("Stop()")
  // ...
}

// A proxy
func (c *CarDouble) Refuel(int amount) error {
  // Forward call to a real object
  return c.realCar(amount)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment