Mock Test

Mock 是一种测试技术,用于模拟程序中的外部依赖(如数据库、API、第三方服务等),以便在单元测试中:

隔离被测函数的逻辑。有时候没办法连接数据库,但是又要保证代码能力,可以使用。

案例

有一个函数叫AddSystemLevel,其中有对数据库查询的几个函数,然后当我想要对AddSystemLevel进行测试时,可以利用mock test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 原始未解耦版本(直接调用数据库)
func AddSystemLevel(nodes []Node) []Node {
// 直接调用数据库方法
systemProjectMapping, err := GetAllSystemNames() // 查数据库
maxId, err := GetMaxNodeID() // 查数据库

// ...其他逻辑
return updatedNodes
}

// 数据库方法
func GetAllSystemNames() (map[string]string, error) {
// 真实数据库操作
var result map[string]string
err := DB.SQL("SELECT ...").Find(&result)
return result, err
}

步骤

定义接口

1
2
3
4
// 定义依赖接口
type NodeService interface {
GetAllSystemNames() (map[string]string, error)
}

原来接口改造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 生产环境真实实现
type DefaultNodeService struct{}

func (d *DefaultNodeService) GetAllSystemNames() (map[string]string, error) {
// 真实数据库操作
var result map[string]string
err := DB.SQL("SELECT ...").Find(&result)
return result, err
}

// 改造成依赖注入版本
func AddSystemLevel(nodes []Node, service NodeService) []Node { // 新增接口参数
systemProjectMapping, err := service.GetAllSystemNames() // 通过接口调用

// ...其他逻辑保持不变
return updatedNodes
}

新建mock_node_service.go 文件

1
2
3
4
5
6
7
8
9
10
11
// mock_node_service.go
type MockNodeService struct {
mock.Mock
}

func (m *MockNodeService) GetAllSystemNames() (map[string]string, error) {
args := m.Called()
return args.Get(0).(map[string]string), args.Error(1)
}


调用AddSystemLevel的方法处

1
2
3
4
5
6
func main() {
service := &DefaultNodeService{} //添加空的service
nodes := AddSystemLevel(initialNodes, service)
// ...
}

测试文件中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
// 都可以让ai生成
func TestAddSystemLevel(t *testing.T) {
// 创建 Mock 对象
mockService := new(MockNodeService)

// 定义 Mock 行为(On 表示期望的调用参数,Return 设置返回值)
mockService.On("GetAllSystemNames").Return(map[string]string{
"proj1": "system1"
}, nil)

// 准备测试数据
nodes := []Node{
{Id: 1, Name: "proj1", Cate: "project"},
}

// 调用被测函数(需将依赖注入到 AddSystemLevel 中)
// 假设 AddSystemLevel 接收一个 NodeService 接口参数:
result := AddSystemLevel(nodes, mockService) // 依赖注入示例

// 验证结果和 Mock 调用
assert.Len(t, result, 2)
mockService.AssertExpectations(t) // 检查所有期望是否被调用
}