Go 单元测试实践

535 阅读1分钟

前言

  • 当我们完成一个模块后,先不着急继续完成其他模块,而是进行单元测试,这样我们能够提前发现当前模块的错误,减少整个项目完成后出现的bug。
  • 可以了解下TDD(测试驱动开发)

1.需要的包

1.常用的包

import (
    //gomonkey : 一个方便的打桩工具
    "github.com/agiledragon/gomonkey"
    
    //testify : 一个方便的断言工具 (最新版本不支持go 1.12,推荐降低版本)
    "github.com/stretchr/testify/assert"
)

2.补充包

import (
    //模拟redis
    "github.com/alicebob/miniredis/v2"
    //模拟sqlmock
    "github.com/DATA-DOG/go-sqlmock"
)

2.外部调用模块

1.person.go

package unittesting

func Eat(s string,t bool) bool {
	return true
}

2.user.go

package unittesting


func Add() bool {
	//调用外部func
	result := Eat("eat",true)

	return result
}

3.单元测试

package unittesting

import (
	"github.com/agiledragon/gomonkey"
	"github.com/stretchr/testify/assert"
	"testing"
)

func TestUser(t *testing.T) {
	t.Run("测试:外部func调用失败",t, func(t *testing.T) {
		//打桩:外部func
		gomonkey.ApplyFunc := gomonkey.ApplyFunc(Eat, func(_ string, _ bool) bool {
			return false  //模拟值
		})
		defer applyFunc.Reset() //如果不重置,后面调用该模块桩的结果不变

		//执行
		actual := Add()

		//断言 actual-shouldEual-模拟值
                assert.Equal(t,false,actual)
	})
}

3.外部方法模块 (为一个方法打桩)

1. person.go (method)

package unittesting

type Person struct {
	name string
}

func (p *Person) Play(s string,t bool) error {
	return nil
}

2.user.go

package unittesting

func Add() error {

	person := Person{
		name: "Tom",
	}

	//调用外部method
	err := person.Play("", false)

	return err
}

3.user_test.go

package unittesting

import (
	"errors"
	"github.com/agiledragon/gomonkey"
	"github.com/stretchr/testify/assert"
	"reflect"
	"testing"
)

func TestUser(t *testing.T) {
	t.Run("测试:外部method调用err",t, func(t *testing.T) {
		var p *Person //注意
		//打桩:method
		gomonkey.ApplyMethod := gomonkey.ApplyMethod(reflect.TypeOf(p), "Play", func(_ *Person, _ string, _ bool) error {
			return errors.New("test Err")
		})
		defer applyMethod.Reset() //如果不重置,后面调用该模块桩的结果不变

		//执行
		actualErr := Add()

		//断言 actual-shouldEual-模拟值
		assert.Equal(t,"test Err",actualErr.Error())
	})
}