Master Go Unit Testing: From Basics to Mocking with GoConvey

This article explains what unit testing is, shows how to write Go unit tests using the testing package, demonstrates more expressive assertions with GoConvey, and introduces mock creation with mockery, providing practical code examples and best‑practice tips for backend developers.

NiuNiu MaTe
NiuNiu MaTe
NiuNiu MaTe
Master Go Unit Testing: From Basics to Mocking with GoConvey

What is Unit Testing?

In computing, unit testing (also called module testing) verifies the correctness of individual program modules, which are the smallest testable parts of an application.

How to Write Unit Tests in Go

Go's testing framework uses files ending with _test.go . The go test command compiles and runs these files. Key elements include naming test files, using TestMain with a testing.M parameter, writing test functions in the form TestXXX(t *testing.T), running all tests with go test, and targeting specific tests with go test -v -run TestFunctionName.

func TestUser(t *testing.T) {
    var u = &User{Age: 15, Name: "alice"}
    if u.Age != 15 {
        t.Error("age err")
    }
    if u.Name != "bob" {
        t.Error("name err")
    }
}

The test runs and reports failures when expectations are not met.

Using GoConvey for Better Assertions

GoConvey adds convenient setup/teardown and a rich set of So assertions, producing clearer failure messages.

func TestUser(t *testing.T) {
    convey.Convey("TestUser", t, func() {
        var u = &User{Age: 15, Name: "alice"}
        convey.So(u.Age, convey.ShouldEqual, 15)
        convey.So(u.Name, convey.ShouldEqual, "bob")
    })
}

Mocking in Go with mockery

When unit tests involve third‑party dependencies, mocking replaces those interfaces with controllable fakes. The mockery tool generates mocks for Go interfaces.

// client.go
package rpc
//go:generate mockery -name=Client

type Client interface {
    Get(key string) (data interface{}, err error)
}

type ClientImpl struct {
    Ct Client
}

func (p *ClientImpl) Get(key string) (data interface{}, err error) {
    if mockCondition {
        return p.Ct.Get(key)
    }
    // real logic
}
// client_test.go
package rpc

import (
    "testing"
    "github.com/stretchr/testify/mock"
    "github.com/smartystreets/goconvey/convey"
)

type User struct {
    Age  int
    Name string
}

func TestMock(t *testing.T) {
    convey.Convey("TestMock", t, func() {
        mc := &mocks.Client{}
        var u = &User{Age: 15, Name: "alice"}
        mc.On("Get", "alice").Return(u, nil)
        ci.Ct = mc
        data, err := ci.Get("alice")
        convey.So(data.Age, convey.ShouldEqual, 15)
    })
}

Conclusion

Unit testing is an essential part of software quality; aiming for high coverage reduces bugs and improves code understanding. Using tools like GoConvey and mockery makes tests more expressive and maintainable.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Gounit testingmockingGoConvey
NiuNiu MaTe
Written by

NiuNiu MaTe

Joined Tencent (nicknamed "Goose Factory") through campus recruitment at a second‑tier university. Career path: Tencent → foreign firm → ByteDance → Tencent. Started as an interviewer at the foreign firm and hopes to help others.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.