範例環境:
- Go 1.18
- Testify 1.7.0
範例專案的module名稱為abc.com/demo
。
主程式
以下為主程式的函式、型別及檔案。
model/employee.go
定義一個Employee
struct型別,為其他函式中使用的參數。
model/employee.go
package model
type Employee struct {
ID int64
Name string
Age int
}
service/employee_service.go
中定義了EmployeeService
介面提供取得資深員工數目的方法GetSrEmployeeNumbers()
與介面的實作型別EmployeeSerivceImpl
。EmployeeSerivceImpl.GetSrEmployeeNumbers()
委託其依賴repo.EmployeeRepo
查詢大於特定年紀的員工。
service/employee_service.go
package serivce
import "abc.com/demo/repo"
type EmployeeService interface {
GetSrEmployeeNumbers() int
}
type EmployeeSerivceImpl struct {
EmpRepo repo.EmployeeRepo
}
func (es *EmployeeSerivceImpl) GetSrEmployeeNumbers(age int) int {
srEmps := es.EmpRepo.FindEmployeesAgeGreaterThan(age)
return len(srEmps)
}
repo/employee_repo.go
中定義了EmployeeRepo
介面提供查詢大於某年紀的員工的方法FindEmployeesAgeGreaterThan()
與介面的實作型別EmployeeRepoImpl
。EmployeeRepoImpl.FindEmployeesAgeGreaterThan()
模擬從資料庫取得員工。
repo/employee_repo.go
package repo
import (
"sort"
"abc.com/demo/model"
)
type EmployeeRepo interface {
FindEmployeesAgeGreaterThan(age int) []model.Employee
}
type EmployeeRepoImpl struct {
}
func (er *EmployeeRepoImpl) FindEmployeesAgeGreaterThan(age int) []model.Employee {
m := map[int]model.Employee{
1: {ID: 1, Name: "John", Age: 33},
2: {ID: 2, Name: "Mary", Age: 21},
3: {ID: 3, Name: "Mike", Age: 45},
}
emps := []model.Employee{}
for _, emp := range m {
if emp.Age > age {
emps = append(emps, emp)
}
}
sort.Slice(emps, func(i, j int) bool {
return emps[i].Age < emps[j].Age // sort by Age asc
})
return emps
}
測試程式
employee_service_test.go
為employee_service.go
的測試程式並使用Testify的mock.Mock
來取代被測對象的中的依賴,並利用mock.On()
設計呼叫mock方法的預期的輸入參數及回傳值。
service/employee_service_test.go
package serivce
import (
"testing"
"abc.com/demo/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
// define mock type
type EmployeeRepoImplMock struct {
mock.Mock
}
// use mock to implments EmployeeRepo's method
func (repoMock *EmployeeRepoImplMock) FindEmployeesAgeGreaterThan(age int) []model.Employee {
args := repoMock.Called(age)
return args.Get(0).([]model.Employee)
}
func TestGetSrEmployeeNumbers_Age40(t *testing.T) {
repoMock := new(EmployeeRepoImplMock)
repoMock.On("FindEmployeesAgeGreaterThan", 40).
Return([]model.Employee{
{ID: 99, Name: "Jack", Age: 70}, // mock return value
})
expected := 1
es := EmployeeSerivceImpl{
EmpRepo: repoMock,
}
actial := es.GetSrEmployeeNumbers(40)
assert.Equal(t, expected, actial)
}
employee_repo_test.go
為employee_repo.go
的測試程式。
repo/employee_repo_test.go
package repo
import (
"testing"
"abc.com/demo/model"
"github.com/stretchr/testify/assert"
)
func TestFindEmployeesAgeGreaterThan30(t *testing.T) {
testCase := struct {
age int
expected []model.Employee
}{
30,
[]model.Employee{
{ID: 1, Name: "John", Age: 33},
{ID: 3, Name: "Mike", Age: 45},
},
}
empRepo := EmployeeRepoImpl{}
actial := empRepo.FindEmployeesAgeGreaterThan(30)
assert.Equal(t, testCase.expected, actial)
}
執行測試
在專案根目錄以命令列輸入go test -v ./...
執行根目錄下所有子目錄中的測試程式。
$ go test -v ./...
? abc.com/demo [no test files]
? abc.com/demo/model [no test files]
=== RUN TestFindEmployeesAgeGreaterThan30
--- PASS: TestFindEmployeesAgeGreaterThan30 (0.00s)
PASS
ok abc.com/demo/repo 0.599s
=== RUN TestGetSrEmployeeNumbers_Age40
--- PASS: TestGetSrEmployeeNumbers_Age40 (0.00s)
PASS
ok abc.com/demo/serivce 0.326s
沒有留言:
張貼留言