Go 單元測試實踐

奇蹟師發表於2021-06-17
  • 當我們完成一個模組後,先不著急繼續完成其他模組,而是進行單元測試,這樣我們能夠提前發現當前模組的錯誤,減少整個專案完成後出現的bug。
  • 可以瞭解下TDD(測試驅動開發)

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"
)

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()

        //斷言 expect --- actual
        assert.Equal(t,false,actual)
    })
}

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()

        //斷言 expect --- actual
        assert.Equal(t,"test Err",actualErr.Error())
    })
}

使用gomonkey進行測試時,進行了打樁,但樁失效(在進行斷點測試的時候能夠成功

問題原因

對行內函數的Stub,go test命令列一定要加上引數才可生效。

解決方案

命令列預設加上-gcflags=all=-l就行了

方法1(推薦使用)

//在測試包內打命令

go test -gcflags "all=-l"

方法2(不推薦使用–無法進行斷點測試)

設定goland

Run->Edit Configurations ->Go Test-> Go tool arguments ->設定 -gcflags “all=-l”

參考

www.jetbrains.com/help/go/run-debu...

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章