You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go单元测试中如何Mock NewSchema调用的SubmittingIdentityHasOU函数?

解决Go单元测试中Mock内部函数的问题

针对你遇到的NewSchema调用SubmittingIdentityHasOU时Mock失效的问题,核心原因是Go的静态编译特性——直接调用包内函数会在编译阶段绑定到实际实现,无法直接Mock。以下是两种可行的改造方案:

方案1:将依赖函数改为包级变量

把SubmittingIdentityHasOU定义为包级函数变量,测试时直接替换该变量即可:

改造业务代码

// 定义包级函数变量,默认指向原实现
var SubmittingIdentityHasOU = func(ctx contractapi.TransactionContextInterface, ou string) bool {
    // 原函数的实际逻辑
}

func NewSchema(ctx contractapi.TransactionContextInterface, groupName string, schemaName string, schemaText string) error {
    // 调用函数变量而非直接调用原函数
    if !SubmittingIdentityHasOU(ctx, "random_string") {
        return errors.New("权限不足")
    }
    // 其他业务逻辑
}

编写测试用例

func TestNewSchema_ValidOU(t *testing.T) {
    // 保存原函数,测试结束后恢复避免影响其他用例
    originalFunc := SubmittingIdentityHasOU
    defer func() { SubmittingIdentityHasOU = originalFunc }()

    // Mock函数返回true
    SubmittingIdentityHasOU = func(ctx contractapi.TransactionContextInterface, ou string) bool {
        return true
    }

    // 构造测试用的TransactionContext(需自行Mock接口实现)
    ctx := mockTransactionContext()
    err := NewSchema(ctx, "test-group", "test-schema", "{}")
    if err != nil {
        t.Fatalf("预期无错误,实际得到:%v", err)
    }
}

func TestNewSchema_InvalidOU(t *testing.T) {
    originalFunc := SubmittingIdentityHasOU
    defer func() { SubmittingIdentityHasOU = originalFunc }()

    // Mock函数返回false
    SubmittingIdentityHasOU = func(ctx contractapi.TransactionContextInterface, ou string) bool {
        return false
    }

    ctx := mockTransactionContext()
    err := NewSchema(ctx, "test-group", "test-schema", "{}")
    if err == nil {
        t.Fatal("预期返回权限不足错误,实际无错误")
    }
    if err.Error() != "权限不足" {
        t.Fatalf("错误信息不符,预期:权限不足,实际:%v", err.Error())
    }
}

方案2:通过接口依赖注入封装

如果业务逻辑复杂,推荐用接口封装依赖,实现更清晰的解耦:

改造业务代码

// 定义权限检查接口
type IdentityChecker interface {
    HasOU(ctx contractapi.TransactionContextInterface, ou string) bool
}

// 默认实现原函数逻辑
type DefaultIdentityChecker struct{}

func (d *DefaultIdentityChecker) HasOU(ctx contractapi.TransactionContextInterface, ou string) bool {
    // 原函数的实际逻辑
}

// 将检查器作为结构体字段,实现依赖注入
type SchemaService struct {
    checker IdentityChecker
}

// 构造函数,默认使用默认检查器
func NewSchemaService() *SchemaService {
    return &SchemaService{
        checker: &DefaultIdentityChecker{},
    }
}

// 把NewSchema改为结构体方法,依赖接口而非直接调用函数
func (s *SchemaService) NewSchema(ctx contractapi.TransactionContextInterface, groupName string, schemaName string, schemaText string) error {
    if !s.checker.HasOU(ctx, "random_string") {
        return errors.New("权限不足")
    }
    // 其他业务逻辑
}

编写测试用例

// 定义Mock检查器
type MockIdentityChecker struct {
    hasOUResult bool
}

func (m *MockIdentityChecker) HasOU(ctx contractapi.TransactionContextInterface, ou string) bool {
    return m.hasOUResult
}

func TestNewSchema_ValidOU(t *testing.T) {
    // 创建Mock检查器,指定返回true
    mockChecker := &MockIdentityChecker{hasOUResult: true}
    service := &SchemaService{checker: mockChecker}

    ctx := mockTransactionContext()
    err := service.NewSchema(ctx, "test-group", "test-schema", "{}")
    if err != nil {
        t.Fatalf("预期无错误,实际得到:%v", err)
    }
}

func TestNewSchema_InvalidOU(t *testing.T) {
    mockChecker := &MockIdentityChecker{hasOUResult: false}
    service := &SchemaService{checker: mockChecker}

    ctx := mockTransactionContext()
    err := service.NewSchema(ctx, "test-group", "test-schema", "{}")
    if err == nil {
        t.Fatal("预期返回权限不足错误,实际无错误")
    }
    if err.Error() != "权限不足" {
        t.Fatalf("错误信息不符,预期:权限不足,实际:%v", err.Error())
    }
}

内容的提问来源于stack exchange,提问作者Fernando Garzón

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 01:23:27