Mocking Methods in Go
Tags: go, unittests, mocking, interfaces
Published: 2017-12-17 05:00:55

---
title: Mocking Methods in Go
published: true
description: 
tags: #go, #unittests, #mocking, #interfaces
---
 
It goes without saying that a battalion of soldiers is as strong as their weakest link. In this context, a piece of code is free of bugs and other issues as its weakest point. **Kent Beck** from facebook once visited us at Andela to give a talk on TDD and throughout his session, it was clear that unit testing is critical part of the software development.

Languages like Python provide standardised libraries and frameworks that make it easy to mock methods and functions inside an impure function or method. With python unit tests are pretty easy thus achieving a 100% test coverage is the norm.

Go or Golang is a light weight language that is not C based. Its syntax is pretty easy, I like to refer to golang as a "_Pythonized version of Java_" due to the similarity of concepts _imported_ from both Java and Python. Golang does not have an official package that supports mocking of methods during unit testing. 

Mocking in golang is done with the help of [interfaces](http://www.golangbootcamp.com/book/interfaces). Mocking in unit testing is important as it ensure that variables, methods and functions modified outside the scope of the function being tested do not affect the test output.

Here is the implementation of mocking.go

```Go
/** mocking.go **/

package main

import "fmt"

type (
	// Values defines interface to be used in mocking
	Values interface {
		GetVolume() int
		GetSurfaceArea() int
	}

	// Measurements defines the measurements used to calculate
	// the surface area and volume of a cube or a cuboid.
	Measurements struct {
		Length int
		Width  int
		Height int
	}
)

// GetVolume calculates and returns the volume of a cube or a cuboid
func (config *Measurements) GetVolume() int {
	return config.Height * config.Length * config.Width
}

// GetSurfaceArea calculates and returns the surface area of a cube or cuboid
func (config *Measurements) GetSurfaceArea() int {
	return (config.Length * config.Width * 2) +
		(config.Length * config.Width * 2) +
		(config.Height * config.Width * 2)
}

// GetVolumeAndArea fetches and returns the volume and the area
func GetVolumeAndArea(val Values) (int, int) {
	return val.GetVolume(), val.GetSurfaceArea()
}

// program execution starts here
func main() {
	var (
		area, volume int

		data = &Measurements{
			Length: 1,
			Height: 5,
			Width:  3,
		}
	)

	volume, area = GetVolumeAndArea(data)

	fmt.Printf("Volume : %d , Area : %d \n", volume, area)
}
```

`GetVolumeAndArea` function accepts an interface as its input parameter. This means that any receiver (_struct used to create a method_) that implements `GetVolume` and `GetSurfaceArea` also implements the `Values` interface.

Mocking of `GetVolume` and `GetSurfaceArea` is done by passing their customized implementations through the struct that acts as their receiver.

Below is how mocking of `GetVolume` and `GetSurfaceArea` should be done using interfaces. No extra libraries or frameworks needed.

```Go
/** mocking_test.go **/

package main

import (
	"strconv"
	"testing"
)

// MockTest helps implement our customized GetVolume and GetSurfaceArea
// needed to mock the original implementation in mocking.go
type MockTest struct {
	Elem int
}

// GetVolume returns the volume of a cube
func (config *MockTest) GetVolume() int {
	return config.Elem * config.Elem * config.Elem
}

// GetSurfaceArea returns the surface area of a cube
func (config *MockTest) GetSurfaceArea() int {
	return config.Elem * config.Elem * 6
}

// TestGetVolumeAndArea tests the functionality of GetVolumeAndArea
func TestGetVolumeAndArea(t *testing.T) {
	for key, val := range map[MockTest][]int{
		MockTest{Elem: 5}: []int{125, 150},
		MockTest{Elem: 2}: []int{8, 24},
		MockTest{Elem: 1}: []int{1, 6},
	} {
		t.Run("Cube side length "+strconv.Itoa(key.Elem), func(t *testing.T) {
			volume, area := GetVolumeAndArea(&key)

			if volume != val[0] {
				t.Errorf("Expected volume to be equal to %d but was equal to %d ",
					volume, val[0])
				t.FailNow()
			}

			if area != val[1] {
				t.Errorf("Expected area to be equal to %d but was equal to %d ",
					area, val[1])
				t.FailNow()
			}
		})
	}
}
```

Apart from mocking, interfaces also helps in separating of concerns such that pieces of code/functions/methods that communicate with each other can be made to run independent of each other.


They also help hide the underlying implementations that should not be exposed to the outside world especially when building an API.


_For any **Clarifications**, **Corrections** or **Complements** reach out to me via Email on mailto:migwindungu0@gmail.com_