为了账号安全,请及时绑定邮箱和手机立即绑定

如何在不同的包中测试未导出的结构字段?

如何在不同的包中测试未导出的结构字段?

Go
catspeake 2023-03-21 16:57:18
我有一个用工厂创建对象的包。这些结构具有未导出的字段,例如:package fetchertype GitFetcher struct {    uri    string}我有另一个包,它解析一些配置文件,然后构建另一个使用上述对象的对象:package configtype Source struct {    fetcher    GitFetcher}我正在尝试测试我的config包裹。我想构建一些预期的对象,但由于我的测试正在进行config并且我的测试GitFetcher正在进行中,fetcher我不能只创建我想要的对象,例如:package configexpected := GitFetcher{    uri: "example.com/repo.git"      // doesn't work. Field isn't exported.}我如何跨包构建对象以进行这样的测试?我不想使用fetcher工厂方法,因为它采用的参数并不简单。
查看完整描述

4 回答

?
蝴蝶刀刀

TA贡献1801条经验 获得超8个赞

绝对可以用未导出的字段测试结构。


它很笨拙,但你可以使用fmt.Sprint().


func isExpectedStruct(myStruct *otherPak.MyStruct) bool {

    expectedStr := "&{1 2}"

    str := fmt.Sprint(myStruct)


    return expectedStr == str

}

或者


如果你只想测试一个特定的领域


func isExpectedField(myStruct *otherPak.MyStruct) bool {

    expectedSubStr := "unexportedField:2"

    str := fmt.Sprintf("%+v", myStruct)

    return strings.Contains(str, expectedSubStr)

}

但仅仅因为你可以并不意味着你应该。


我认为在大多数情况下,将字段更改为导出或使用模拟会更好,但如果由于某种原因这些不是选项,这会为您提供另一种选择。


查看完整回答
反对 回复 2023-03-21
?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

如果您没有太多需要测试的属性,那么一种(hacky?)方法是为该属性创建一个 getter 函数。


例如,在包中创建这样的东西:


func (g *gitFetcher) GetUri() string {

    return g.uri

}

在你的模拟中,你可以拥有


type GitFetcherMock struct {

    mock.Mock

}


func (g *GitFetcherMock) GetUri() string {

    args := g.Called()

    return args.Get(0)

并且您可以在实际代码中使用实际 URI 的任何地方传入 GetUri()。


查看完整回答
反对 回复 2023-03-21
?
一只甜甜圈

TA贡献1836条经验 获得超5个赞

如何测试未导出的 [...] 不同的包?

一点也不。不可撤销,请勿尝试。

(如果未导出的东西有一个导出的方法,那么你可以调用这个方法。)


查看完整回答
反对 回复 2023-03-21
?
动漫人物

TA贡献1815条经验 获得超10个赞

没有直接的方法可以实现这一点。您有多种选择来实现类似的目标,所有这些都有自己的权衡。由您决定哪种权衡最适合您的情况。

一般来说,我会按以下顺序尝试:

  1. 使包config依赖于接口而不是结构GitFetcher。这样你就可以GitFetcher在你的测试中模拟。

  2. 添加一个额外的工厂方法,专门用于可以GitFetcher更容易构建的测试。

  3. 将未导出的字段导出。

  4. 简单地组合包。这样您就可以访问测试中两个对象的未导出字段。


查看完整回答
反对 回复 2023-03-21
  • 4 回答
  • 0 关注
  • 102 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信