Hello everyone!

We have been investing plenty of personal time and energy for many years to share our knowledge with you all. However, we now need your help to keep this blog running. All you have to do is just click one of the adverts on the site, otherwise it will sadly be taken down due to hosting etc. costs. Thank you.

In this example we are going to test a function but by mocking it. Mocking is important because sometimes we don't want to run the real logic of a given function for any given reason.


Installation


Install mockery binary to OS with go get github.com/vektra/mockery/v2/.../ command first. This will also add relevant entries to go.mod/sum but you can remove them all because you will have to run go get -u http://github.com/stretchr/testify command which will be enough.


Example


package file

import (
"image"
"mime"
"os"

_ "image/gif"
_ "image/jpeg"
_ "image/png"
)

type Manager interface {
Mime(path string) (string, error)
}

type Image struct {}

func (Image) Mime(path string) (string, error) {
fil, err := os.Open(path)
if err != nil {
return "", err
}
defer fil.Close()

_, mim, err := image.DecodeConfig(fil)
if err != nil {
return "", err
}

return mime.TypeByExtension("." + mim), nil
}

Test


There is a Manager interface in ./internal/file/file.go file and we are creating its mock ./internal/file/mocks/manager.go file.


$ mockery --name Manager --dir ./internal/file/ --output ./internal/file/mocks --filename manager.go

22 Jul 20 10:21 BST INF Starting mockery dry-run=false version=(devel)
22 Jul 20 10:21 BST INF Walking dry-run=false version=(devel)
22 Jul 20 10:21 BST INF Generating mock dry-run=false interface=Manager qualified-name=github.com/you/client/internal/file version=(devel)

package file

import (
"fmt"
"testing"

"github.com/you/client/internal/file/mocks"

"github.com/stretchr/testify/assert"
)

func TestFile_Mime(t *testing.T) {
mockFile := &mocks.Manager{}

t.Run("file not found error", func(t *testing.T) {
mockFile.
On("Mime", "some-file.png").
Once().
Return("", fmt.Errorf("file not found"))

mim, err := mockFile.Mime("some-file.png")

assert.Empty(t, mim)
assert.Error(t, err, "file not found")
})

t.Run("config decoding error", func(t *testing.T) {
mockFile.
On("Mime", "some-file.png").
Once().
Return("", fmt.Errorf("config error"))

mim, err := mockFile.Mime("some-file.png")

assert.Empty(t, mim)
assert.Error(t, err, "config error")
})

t.Run("successfully getting mime", func(t *testing.T) {
mockFile.
On("Mime", "some-file.png").
Once().
Return("image/png", nil)

mim, err := mockFile.Mime("some-file.png")

assert.Equal(t, "image/png", mim)
assert.NoError(t, err)
})
}

$ go test -v -run TestFile_Mime ./internal/file/

=== RUN TestFile_Mime
=== RUN TestFile_Mime/file_not_found_error
=== RUN TestFile_Mime/config_decoding_error
=== RUN TestFile_Mime/successfully_getting_mime
--- PASS: TestFile_Mime (0.00s)
--- PASS: TestFile_Mime/file_not_found_error (0.00s)
--- PASS: TestFile_Mime/config_decoding_error (0.00s)
--- PASS: TestFile_Mime/successfully_getting_mime (0.00s)
PASS