179 lines
4.1 KiB
Go
179 lines
4.1 KiB
Go
package handler_test
|
|
|
|
// TODO 使用 mock测试 handler
|
|
|
|
// 一、安装 GoMock
|
|
// 首先需要安装 GoMock 和 mockgen 工具:
|
|
|
|
// bash
|
|
// 复制
|
|
// # 安装 GoMock 包
|
|
// go get github.com/golang/mock/gomock
|
|
|
|
// # 安装 mockgen 工具
|
|
// go install github.com/golang/mock/mockgen@latest
|
|
// 二、基本使用步骤
|
|
// 1. 定义接口
|
|
// 假设我们有一个简单的接口:
|
|
|
|
// go
|
|
// 复制
|
|
// // greeter.go
|
|
// package main
|
|
|
|
// type Greeter interface {
|
|
// Greet(name string) string
|
|
// }
|
|
// 2. 生成 mock 代码
|
|
// 使用 mockgen 为接口生成 mock 实现:
|
|
|
|
// bash
|
|
// 复制
|
|
// mockgen -source=greeter.go -destination=mock_greeter.go -package=main
|
|
// 这会生成一个 mock_greeter.go 文件,包含 MockGreeter 结构体。
|
|
|
|
// 3. 编写测试代码
|
|
// go
|
|
// 复制
|
|
// // greeter_test.go
|
|
// package main
|
|
|
|
// import (
|
|
// "testing"
|
|
|
|
// "github.com/golang/mock/gomock"
|
|
// )
|
|
|
|
// func TestGreet(t *testing.T) {
|
|
// // 创建控制器
|
|
// ctrl := gomock.NewController(t)
|
|
// defer ctrl.Finish() // 断言所有期望都被满足
|
|
|
|
// // 创建 mock 对象
|
|
// mockGreeter := NewMockGreeter(ctrl)
|
|
|
|
// // 设置期望
|
|
// mockGreeter.EXPECT().
|
|
// Greet("Alice").
|
|
// Return("Hello, Alice!").
|
|
// Times(1)
|
|
|
|
// // 使用 mock 对象
|
|
// result := mockGreeter.Greet("Alice")
|
|
|
|
// // 验证结果
|
|
// if result != "Hello, Alice!" {
|
|
// t.Errorf("Expected 'Hello, Alice!', got '%s'", result)
|
|
// }
|
|
// }
|
|
// 三、高级功能
|
|
// 1. 参数匹配
|
|
// GoMock 提供了多种参数匹配方式:
|
|
|
|
// go
|
|
// 复制
|
|
// // 精确匹配
|
|
// mockGreeter.EXPECT().Greet("Alice")
|
|
|
|
// // 任意值匹配
|
|
// mockGreeter.EXPECT().Greet(gomock.Any())
|
|
|
|
// // 自定义匹配
|
|
// mockGreeter.EXPECT().Greet(gomock.AssignableToTypeOf("")).DoAndReturn(
|
|
// func(name string) string {
|
|
// return "Hello, " + name + "!"
|
|
// },
|
|
// )
|
|
// 2. 调用次数控制
|
|
// go
|
|
// 复制
|
|
// // 精确调用次数
|
|
// mockGreeter.EXPECT().Greet("Alice").Times(3)
|
|
|
|
// // 至少调用一次
|
|
// mockGreeter.EXPECT().Greet("Alice").MinTimes(1)
|
|
|
|
// // 最多调用一次
|
|
// mockGreeter.EXPECT().Greet("Alice").MaxTimes(1)
|
|
|
|
// // 任意次数(0或多次)
|
|
// mockGreeter.EXPECT().Greet("Alice").AnyTimes()
|
|
// 3. 调用顺序控制
|
|
// go
|
|
// 复制
|
|
// gomock.InOrder(
|
|
// mockGreeter.EXPECT().Greet("Alice"),
|
|
// mockGreeter.EXPECT().Greet("Bob"),
|
|
// )
|
|
// 4. 模拟副作用
|
|
// go
|
|
// 复制
|
|
// // 使用 Do
|
|
// mockGreeter.EXPECT().Greet("Alice").Do(func(name string) {
|
|
// t.Logf("Greet was called with %s", name)
|
|
// })
|
|
|
|
// // 使用 DoAndReturn
|
|
// mockGreeter.EXPECT().Greet("Alice").DoAndReturn(
|
|
// func(name string) string {
|
|
// return "Hi, " + name + "!"
|
|
// },
|
|
// )
|
|
// 四、实际应用示例
|
|
// 假设我们有一个服务依赖 Greeter 接口:
|
|
|
|
// go
|
|
// 复制
|
|
// // greeter_service.go
|
|
// package main
|
|
|
|
// type GreeterService struct {
|
|
// greeter Greeter
|
|
// }
|
|
|
|
// func (s *GreeterService) WelcomePeople(names []string) []string {
|
|
// var greetings []string
|
|
// for _, name := range names {
|
|
// greetings = append(greetings, s.greeter.Greet(name))
|
|
// }
|
|
// return greetings
|
|
// }
|
|
// 对应的测试:
|
|
|
|
// go
|
|
// 复制
|
|
// // greeter_service_test.go
|
|
// package main
|
|
|
|
// import (
|
|
// "testing"
|
|
|
|
// "github.com/golang/mock/gomock"
|
|
// )
|
|
|
|
// func TestWelcomePeople(t *testing.T) {
|
|
// ctrl := gomock.NewController(t)
|
|
// defer ctrl.Finish()
|
|
|
|
// mockGreeter := NewMockGreeter(ctrl)
|
|
// service := &GreeterService{greeter: mockGreeter}
|
|
|
|
// // 设置期望
|
|
// mockGreeter.EXPECT().Greet("Alice").Return("Hello, Alice!")
|
|
// mockGreeter.EXPECT().Greet("Bob").Return("Hello, Bob!")
|
|
|
|
// // 测试
|
|
// result := service.WelcomePeople([]string{"Alice", "Bob"})
|
|
|
|
// // 验证
|
|
// expected := []string{"Hello, Alice!", "Hello, Bob!"}
|
|
// if len(result) != len(expected) {
|
|
// t.Fatalf("Expected %d greetings, got %d", len(expected), len(result))
|
|
// }
|
|
// for i := range expected {
|
|
// if result[i] != expected[i] {
|
|
// t.Errorf("At index %d: expected %q, got %q", i, expected[i], result[i])
|
|
// }
|
|
// }
|
|
// }
|