golang学习之go单元测试(二)

一、表格驱动测试

表格测试,把测试数据放在数据表格中进行多组数据测试

func Add(num1 int, num2 int) int {
    
    
	return num1 + num2
}
func TestAdd(t *testing.T) {
    
    
	type args struct {
    
    
		num1 int
		num2 int
	}

	testTable := []struct {
    
    
		name string
		args args
		want int
	}{
    
    
		{
    
    
			name: "Add",
			args: args{
    
    1, 1},
			want: 3,
		},
		{
    
    
			name: "Add",
			args: args{
    
    1, 0},
			want: 1,
		},
	}

	for _, tt := range testTable {
    
    
		t.Run(tt.name, func(t *testing.T) {
    
    
			if result := Add(tt.args.num1, tt.args.num2); result != tt.want {
    
    
				t.Errorf(tt.name +" result is %v, want %v", result, tt.want)
			}
		})
	}
}

二、mock函数测试

当要测试的函数依赖其他函数时,可以mock依赖函数进行测试

1、mock测试工具包

go get github.com/bouk/monkey

2、待测试函数Add()依赖函数calculate()

func Add(num1 int) int {
    
    
	num2 := calculate()
	return num1 + num2
}

func calculate() int {
    
    
	//计算
	return 1
}

3、测试示例

func TestAdd(t *testing.T) {
    
    
	// 模拟calculate函数返回 1
	guard := monkey.Patch(calculate, func() int {
    
    
		return 1
	})
	guard.Unpatch()

	type args struct {
    
    
		num1 int
	}

	testTable := []struct {
    
    
		name string
		args args
		want int
	}{
    
    
		{
    
    
			name: "Add",
			args: args{
    
    1},
			want: 3,
		},
		{
    
    
			name: "Add",
			args: args{
    
    1},
			want: 2,
		},
	}

	for _, tt := range testTable {
    
    
		t.Run(tt.name, func(t *testing.T) {
    
    
			if result := Add(tt.args.num1); result != tt.want {
    
    
				t.Errorf(tt.name+" result is %v, want %v", result, tt.want)
			}
		})
	}
}

三、mock方法测试

1、待测试函数add(),依赖Adder的方法Calculate()

func Add(num1 int) int {
    
    
	adder := &Adder{
    
    }
	num2 := adder.Calculate()
	return num1 + num2
}

type Adder struct {
    
    
}

func (adder *Adder) Calculate() int {
    
    
	//计算
	return 1
}

2、测试示例

func TestAdd(t *testing.T) {
    
    
	adder := &Adder{
    
    }
	// 模拟方法返回
	guard := monkey.PatchInstanceMethod(reflect.TypeOf(adder), "Calculate", func(adder *Adder) int {
    
    
		return 1
	})
	guard.Unpatch()

	type args struct {
    
    
		num1 int
	}

	testTable := []struct {
    
    
		name string
		args args
		want int
	}{
    
    
		{
    
    
			name: "Add",
			args: args{
    
    1},
			want: 2,
		},
		{
    
    
			name: "Add",
			args: args{
    
    0},
			want: 1,
		},
	}

	for _, tt := range testTable {
    
    
		t.Run(tt.name, func(t *testing.T) {
    
    
			if result := Add(tt.args.num1); result != tt.want {
    
    
				t.Errorf(tt.name+" result is %v, want %v", result, tt.want)
			}
		})
	}
}

四、mock数据库测试

github 官方示例

go get github.com/DATA-DOG/go-sqlmock

1、待测试内容

扫描二维码关注公众号,回复: 14697549 查看本文章
package main

import (
	"database/sql"

	_ "github.com/go-sql-driver/mysql"
)

func recordStats(db *sql.DB, userID, productID int64) (err error) {
    
    
	tx, err := db.Begin()
	if err != nil {
    
    
		return
	}

	defer func() {
    
    
		switch err {
    
    
		case nil:
			err = tx.Commit()
		default:
			tx.Rollback()
		}
	}()

	if _, err = tx.Exec("UPDATE products SET views = views + 1"); err != nil {
    
    
		return
	}
	if _, err = tx.Exec("INSERT INTO product_viewers (user_id, product_id) VALUES (?, ?)", userID, productID); err != nil {
    
    
		return
	}
	return
}

func main() {
    
    
	// @NOTE: the real connection is not required for tests
	db, err := sql.Open("mysql", "root@/blog")
	if err != nil {
    
    
		panic(err)
	}
	defer db.Close()

	if err = recordStats(db, 1 /*some user id*/, 5 /*some product id*/); err != nil {
    
    
		panic(err)
	}
}

2、测试内容

package main

import (
	"fmt"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
)

// a successful case
func TestShouldUpdateStats(t *testing.T) {
    
    
	db, mock, err := sqlmock.New()
	if err != nil {
    
    
		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
	}
	defer db.Close()

	mock.ExpectBegin()
	mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
	mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnResult(sqlmock.NewResult(1, 1))
	mock.ExpectCommit()

	// now we execute our method
	if err = recordStats(db, 2, 3); err != nil {
    
    
		t.Errorf("error was not expected while updating stats: %s", err)
	}

	// we make sure that all expectations were met
	if err := mock.ExpectationsWereMet(); err != nil {
    
    
		t.Errorf("there were unfulfilled expectations: %s", err)
	}
}

// a failing test case
func TestShouldRollbackStatUpdatesOnFailure(t *testing.T) {
    
    
	db, mock, err := sqlmock.New()
	if err != nil {
    
    
		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
	}
	defer db.Close()

	mock.ExpectBegin()
	mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
	mock.ExpectExec("INSERT INTO product_viewers").
		WithArgs(2, 3).
		WillReturnError(fmt.Errorf("some error"))
	mock.ExpectRollback()

	// now we execute our method
	if err = recordStats(db, 2, 3); err == nil {
    
    
		t.Errorf("was expecting an error, but there was none")
	}

	// we make sure that all expectations were met
	if err := mock.ExpectationsWereMet(); err != nil {
    
    
		t.Errorf("there were unfulfilled expectations: %s", err)
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_56349119/article/details/127828256