範例環境:
- Go 1.16
- Testify 1.7
範例專案的module名稱為abc.com/demo
。
主程式
以下為主程式的函式、型別及檔案。
model/employee.go
僅定義一個Employee
struct型別,為其他函式中使用的參數。
model/employee.go
package model
type Employee struct {
Id int
Name string
Age int
}
service/calculator.go
中定義了CalculatorService
介面供計算整數加減的方法Plus()
及Minus()
與介面的實作型別Calculator
。為下面測試程式要mock的對象。
service/calculator.go
package serivce
type CalculatorService interface {
Plus(int, int) int
Minus(int, int) int
}
type Calculator struct {
}
func (c Calculator) Plus(x, y int) int {
return x + y
}
func (c Calculator) Minus(x, y int) int {
return x - y
}
main.go
的兩個函式AddAge()
及AgeDiff()
用來計算員工年齡相關邏輯,兩函式皆依賴CalculatorService
介面提供的計算方法。兩函式為下面main_test.go
測試程式要測試的對象
main.go
package main
import (
"errors"
"abc.com/demo/model"
"abc.com/demo/serivce"
)
func AddAge(x int, emp model.Employee, calService serivce.CalculatorService) (int, error) {
if (emp == model.Employee{}) {
return -1, errors.New("emp is empty")
}
return calService.Plus(x, emp.Age), nil
}
func AgeDiff(emp1, emp2 model.Employee, calService serivce.CalculatorService) (int, error) {
if (emp1 == model.Employee{}) || (emp2 == model.Employee{}) {
return 0, errors.New("one emp is empty")
}
return calService.Minus(emp1.Age, emp2.Age), nil
}
測試程式
main_test.go
為main.go
的測試程式並使用Testify的mock.Mock
來取代被測對象的中的依賴,並利用mock.On()
設計呼叫mock方法的預期的輸入參數及回傳值。
main_test.go
package main
import (
"testing"
"abc.com/demo/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
// define mock type
type CalculatorMock struct {
mock.Mock
}
// use mock to implments CalculatorService's method
func (calMock *CalculatorMock) Plus(x, y int) int {
args := calMock.Called(x, y)
return args.Int(0)
}
func (calMock *CalculatorMock) Minus(x, y int) int {
args := calMock.Called(x, y)
return args.Int(0)
}
func TestAddAge(t *testing.T) {
calMock := new(CalculatorMock) // create mock instance
calMock.On("Plus", 1, 33).Return(34) // setup mock method arguments and return value
testCase := struct {
x int
emp model.Employee
expected int
}{
1,
model.Employee{Id: 1, Name: "John", Age: 33},
34,
}
actual, _ := AddAge(testCase.x, testCase.emp, calMock) // pass test arguments and mock to replace real one
assert.Equal(t, testCase.expected, actual)
}
func TestAgeDiff(t *testing.T) {
calMock := new(CalculatorMock)
calMock.On("Minus", 33, 23).Return(10)
testCase := struct {
emp1 model.Employee
emp2 model.Employee
expected int
}{
model.Employee{Id: 1, Name: "John", Age: 33},
model.Employee{Id: 2, Name: "Mary", Age: 23},
10,
}
actual, _ := AgeDiff(testCase.emp1, testCase.emp2, calMock)
assert.Equal(t, testCase.expected, actual)
}
要能mock依賴方法的重點在於,依賴方法須為介面方法如此才能在測試程式中以mock實作來替代。
執行測試
在專案根目錄以命令列輸入go test -v
執行測試。
$ go test -v
=== RUN TestAddAge
--- PASS: TestAddAge (0.00s)
=== RUN TestAgeDiff
--- PASS: TestAgeDiff (0.00s)
PASS
ok abc.com/demo 0.335s
參考github。
沒有留言:
張貼留言