定义

Stub(桩)是 Test Double(测试替身)的重要类型。

Stub(桩)是用于替代真实依赖,但会返回“固定的、预设的”结果的对象。

Stub 是一种测试替身,用来替代真实依赖,返回预设的、固定的数据,使单元测试可控、快速、可靠。

用途

  1. 控制依赖的返回结果:数据库查询、三方 API 返回、RPC 结果……
  2. 模拟各种测试场景:查询成功、查询失败、超时、无数据…..
  3. 让单元测试更快、更稳定、更可控:不用访问真实网络 / 数据库,执行速度飞快。

示例

假设有如下函数

1
2
3
4
5
6
7
func GetUserNameByID(repo UserRepository,id int)string{
user,err:=repo.FindByID(id)
if err!=nil{
return "unknown"
}
return user.Name
}

可以自由控制返回的数据,Stub实现为:

1
2
3
4
5
6
7
8
9
10
11
type StubUserRepository struct{
users map[int]User
err error
}

func (s StubUserRepository) FindByID(id int)(User ,error){
if s.err!=nil{
return User{},s.err
}
return s.users[id],nil
}

Stub的单元测试

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
func TestGetUserNameByID_Success(t *testing.T){
stubRepo:=StubUserRepository{
users:map[int]User{
1:{ID:1,Name:"Alice"},
},
}

name:=GetUserNameByID(stubRepo,1)

if name!="Alice"{
t.Error("expected Alice,got %s",name)
}
}

func TestGetUserNameByID_Error(t *testing.T){
stubRepo:=StubUserRepository{
err:=errors.New("db error"),
}

name:=GetUserNameByID(stubRepo,1)

if name!="unknown"{
t.Errorf("expected unknown,got %s",name)
}
}