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

我有一个用工厂创建对象的包。这些结构具有未导出的字段,例如:


package fetcher

type GitFetcher struct {

    uri    string

}

我有另一个包,它解析一些配置文件,然后构建另一个使用上述对象的对象:


package config

type Source struct {

    fetcher    GitFetcher

}

我正在尝试测试我的config包裹。我想构建一些预期的对象,但由于我的测试正在进行config并且我的测试GitFetcher正在进行中,fetcher我不能只创建我想要的对象,例如:


package config

expected := GitFetcher{

    uri: "example.com/repo.git"      // doesn't work. Field isn't exported.

}

我如何跨包构建对象以进行这样的测试?我不想使用fetcher工厂方法,因为它采用的参数并不简单。


catspeake
浏览 103回答 4
4回答

蝴蝶刀刀

绝对可以用未导出的字段测试结构。它很笨拙,但你可以使用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)}但仅仅因为你可以并不意味着你应该。我认为在大多数情况下,将字段更改为导出或使用模拟会更好,但如果由于某种原因这些不是选项,这会为您提供另一种选择。

牛魔王的故事

如果您没有太多需要测试的属性,那么一种(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()。

一只甜甜圈

如何测试未导出的 [...] 不同的包?一点也不。不可撤销,请勿尝试。(如果未导出的东西有一个导出的方法,那么你可以调用这个方法。)

动漫人物

没有直接的方法可以实现这一点。您有多种选择来实现类似的目标,所有这些都有自己的权衡。由您决定哪种权衡最适合您的情况。一般来说,我会按以下顺序尝试:使包config依赖于接口而不是结构GitFetcher。这样你就可以GitFetcher在你的测试中模拟。添加一个额外的工厂方法,专门用于可以GitFetcher更容易构建的测试。将未导出的字段导出。简单地组合包。这样您就可以访问测试中两个对象的未导出字段。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go