登录
首页 >  Golang >  Go问答

在结构内部的方法中测试错误响应

来源:stackoverflow

时间:2024-04-15 11:12:35 140浏览 收藏

“纵有疾风来,人生不言弃”,这句话送给正在学习Golang的朋友们,也希望在阅读本文《在结构内部的方法中测试错误响应》后,能够真的帮助到大家。我也会在后续的文章中,陆续更新Golang相关的技术文章,有好的建议欢迎大家在评论留言,非常感谢!

问题内容

我正在编写单元测试,并且我想编写一个单元测试,断言结构体 (foo.start) 上的公共方法可以正确处理来自结构体 (foo.internal) 上的内部方法的错误响应。

本质上我想获得对我的代码的这一部分的测试覆盖率:

if err != nil {
    return err
}

这是代码和相关测试的示例,该示例不起作用(但可以在 python 中工作)

# example.go

package example

import "fmt"

type fooapi interface {
    start() error
    internal(string) (string, error)
}

type foo struct {
    fooapi
}

func (foo foo) start() (err error) {

    data, err := foo.internal("bar")
    if err != nil {
        return err
    }

    fmt.println(data)
    return err
}

func (foo foo) internal(input string) (output string, err error) {
    return output, err
}
# example_test.go

package example

import (
    "testing"

    "github.com/pkg/errors"
)

type MockFoo struct {
    FooAPI
}

func (foo MockFoo) internal(input string) (output string, err error) {
    return output, errors.New("big error")
}

func TestStart(t *testing.T) {
    tdata := []struct {
        testCase        string
        expectedAnError bool
        foo             FooAPI
    }{
        {
            testCase:        "standard_case",
            expectedAnError: false,
            foo:             Foo{},
        },
        {
            testCase:        "error_case",
            expectedAnError: true,
            foo:             MockFoo{},
        },
    }
    for _, test := range tdata {
        t.Run(test.testCase, func(t *testing.T) {
            // The function under test
            test.foo.Start = Foo.Start // <= this doesn't work
            err := test.foo.Start()

            // Assertion 1
            if test.expectedAnError == false && err != nil {
                t.Error(err.Error())
            }

            // Assertion 2
            if test.expectedAnError == true && err == nil {
                t.Error("expected an error, but there was none!")
            }
        })
    }
}

我对纠正特定示例不太感兴趣,更多的是我的目标是获得 foo.start 错误处理的测试覆盖率。我觉得接口或指针有一些技巧可以帮助我冲过终点线?


解决方案


https://stackoverflow.com/a/48206430/3055558 的启发,我想出了一个解决方案

使用 internal{{ your struct }} 结构和关联的接口,并模拟它。

# example.go

package example

import "fmt"

type internalfooapi interface {
    internalbehavior(string) (string, error)
}

type foo struct {
    internal internalfooapi
}

type internalfoo struct{}

func newfoo(internal internalfooapi) foo {
    return foo{
        internal: internal,
    }
}

func (foo foo) start() (err error) {

    data, err := foo.internal.internalbehavior("bar")
    if err != nil {
        return err
    }

    fmt.println(data)
    return err
}

func (foo internalfoo) internalbehavior(input string) (output string, err error) {
    return output, err
}
# example_test.go

package example

import (
    "testing"

    "github.com/pkg/errors"
)

type mockInternalFoo struct{}

type mockInternalFooWithErrors struct{}

func (foo mockInternalFoo) internalBehavior(input string) (output string, err error) {
    return output, err
}

func (foo mockInternalFooWithErrors) internalBehavior(input string) (output string, err error) {
    return output, errors.New("big error")
}

func TestStart(t *testing.T) {
    tdata := []struct {
        testCase        string
        expectedAnError bool
        foo             Foo
    }{
        {
            testCase:        "standard_case",
            expectedAnError: false,
            foo:             NewFoo(internalFoo{}),
        },
        {
            testCase:        "mock_case",
            expectedAnError: false,
            foo:             NewFoo(mockInternalFoo{}),
        },
        {
            testCase:        "error_case",
            expectedAnError: true,
            foo:             NewFoo(mockInternalFooWithErrors{}),
        },
    }
    for _, test := range tdata {
        t.Run(test.testCase, func(t *testing.T) {
            // The function under test
            err := test.foo.Start()

            // Assertion 1
            if test.expectedAnError == false && err != nil {
                t.Error(err.Error())
            }

            // Assertion 2
            if test.expectedAnError == true && err == nil {
                t.Error("expected an error, but there was none!")
            }
        })
    }
}

到这里,我们也就讲完了《在结构内部的方法中测试错误响应》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>