Golang泛型Mock库gs-mock发布:类型安全的模拟测试工具

Golang泛型Mock库gs-mock发布:类型安全的模拟测试工具 大家好 :waving_hand:,

我想分享一个我一直在做的项目:gs-mock —— 一个现代的、类型安全的 Go 模拟库,完全支持泛型

为什么需要另一个模拟库?

传统的 Go 模拟工具通常:

  • 严重依赖反射,导致运行时类型错误。
  • 需要冗长的设置代码。
  • 未能充分利用 Go 1.18+ 的泛型特性。

gs-mock 通过提供编译时安全性和更简洁的 API 来解决这些问题。


:sparkles: 主要特性

  • 类型安全:使用 Go 泛型构建,确保没有运行时意外。
  • 多种模拟模式
    • Handle:直接处理函数调用。
    • When/Return:有条件地返回结果。
  • 灵活的匹配:支持最多 5 个参数和 5 个返回值。
  • 上下文集成:与 context.Context 无缝协作。
  • 自动重置:使用 Manager.Reset() 轻松重置所有模拟。
  • 清晰的错误信息:当模拟缺失或重复时,提供详细的 panic 信息。

:rocket: 快速示例

type Repository[T any] interface {
    FindByID(id string) (T, error)
}

// 生成的模拟:RepositoryMockImpl[T]

func TestRepositoryMock(t *testing.T) {
    repo := NewRepositoryMockImpl[int](gsmock.NewManager())

    // 当没有注册模拟时,预期会发生 panic
    assert.Panic(t, func() {
        _, _ = repo.FindByID("1")
    }, "no mock code matched")

    // 注册行为
    repo.MockFindByID().Handle(func(id string) (int, error) {
        return 42, nil
    })

    v, err := repo.FindByID("1")
    assert.Nil(t, err)
    assert.Equal(t, v, 42)
}

:gear: 安装

gs-mock 附带一个代码生成工具:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/go-spring/gs/HEAD/install.sh)"

然后在你的代码中:

//go:generate gs mock -o service_mock.go

:open_file_folder: GitHub

:backhand_index_pointing_right: https://github.com/go-spring/gs-mock

我非常欢迎反馈、贡献和实际测试报告。 如果你发现任何缺失的功能,请随时提出问题或提交 PR!

谢谢!


更多关于Golang泛型Mock库gs-mock发布:类型安全的模拟测试工具的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang泛型Mock库gs-mock发布:类型安全的模拟测试工具的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


gs-mock 看起来是一个很有前景的 Go 泛型 Mock 库,它确实解决了传统反射-based 模拟库的一些痛点。以下是一个更深入的技术示例,展示其类型安全和泛型能力:

// 定义泛型接口
type Cache[T any] interface {
    Get(key string) (T, bool)
    Set(key string, value T)
    Delete(key string) error
}

// 使用 gs-mock 生成的模拟代码
func TestCacheMock(t *testing.T) {
    mgr := gsmock.NewManager()
    cache := NewCacheMockImpl[string](mgr)
    
    // 类型安全的模拟设置
    cache.MockGet().
        When(gsmock.Eq("user:1")).
        Return("John Doe", true)
    
    cache.MockGet().
        When(gsmock.Eq("user:2")).
        Return("", false)
    
    // 编译时类型检查
    value, found := cache.Get("user:1")
    assert.Equal(t, "John Doe", value)
    assert.True(t, found)
    
    // 处理函数模拟
    cache.MockDelete().Handle(func(key string) error {
        if key == "protected" {
            return errors.New("cannot delete protected key")
        }
        return nil
    })
    
    err := cache.Delete("protected")
    assert.Error(t, err)
    
    // 重置所有模拟
    mgr.Reset()
}

关键优势:

  1. 编译时类型安全:泛型确保模拟方法签名与接口完全匹配
  2. 清晰的 API 设计When/Return 模式提供直观的测试设置
  3. 上下文支持:内置 context.Context 处理
// 上下文示例
type Service interface {
    Process(ctx context.Context, data []byte) (int, error)
}

func TestServiceWithContext(t *testing.T) {
    svc := NewServiceMockImpl(gsmock.NewManager())
    
    svc.MockProcess().Handle(func(ctx context.Context, data []byte) (int, error) {
        if ctx.Err() != nil {
            return 0, ctx.Err()
        }
        return len(data), nil
    })
    
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    
    result, err := svc.Process(ctx, []byte("test"))
    assert.Equal(t, 4, result)
    assert.Nil(t, err)
}

这个库的泛型实现确实为 Go 测试带来了更类型安全的方式,减少了运行时错误的风险。

回到顶部