如何测试功能而不重复?

时间:2019-08-09 03:26:57

标签: go testing

我有一个函数(主),该函数调用其他函数(子)。 我已经为子功能编写了单元测试,现在想为主要功能编写单元测试。问题是如何在不复制子函数逻辑并假设子逻辑在主函数测试中的情况下测试主函数(例如,在其中模拟对DB的调用)。

这里是一个例子:


type A struct {
    db DB
}

func (a *A) m(i int) bool {
    if a.s1(i) {
        return false
    }

    if a.s2(i) {
        return false
    }

    if i % 2 == 0 {
        return false
    }

    return true
}

func (a *A) s1(i int) bool {
    // some condition check with DB call here
    return true
}

func (a *A) s2(i int) bool {
    // some condition check with DB call here
    return true
}

示例测试代码(不检查正确性,是示例):


func TestS1(t *testing.T) {
    m := &mockDB{}
    m.On("Check", 5).Return(true)
    a := &A{db: m}
    res := a.s1(5)
    if res == true {
        t.Error("got true")
    }
}

func TestS2(t *testing.T) {
    m := &mockDB{}
    m.On("Exists", 5).Return(true)
    a := &A{db: m}
    res := a.s1(5)
    if res == true {
        t.Error("got true")
    }
}

func TestM(t *testing.T) {
    m := &mockDB{}
    // how do i remove this duplication?
    m.On("Check", 5).Return(true)
    m.On("Exists", 5).Return(true)
    a := &A{db: m}
    res := a.m(5)
    if res == true {
        t.Error("got true")
    }
}

2 个答案:

答案 0 :(得分:1)

如果您使用setup来运行子测试,则可以具有类似t.Run的语义。

func TestSAndM(t *testing.T) {
    // setup mock
    m := &mock{}
    m.On("Check", 5).Return(true)
    m.On("Exists", 5).Return(true)

    t.Run("S1", …)

    t.Run("S2", …)

    t.Run("M", …)
}

在此处查看有效的示例:https://play.golang.org/p/KEmCYcxI0uS

正在运行的子测试:https://golang.org/pkg/testing/#T.Run

答案 1 :(得分:1)

典型的解决方法是仅测试公共接口的完整流程。如果(导出的)主函数调用子函数,则子函数的测试将在主函数的测试中进行。您无需单独测试子功能,因为无论如何只能通过主功能来访问这些功能。如果对主函数的测试通过了,则意味着子函数也通过了。

但是,让我们假设这不是您正在寻找的信息或您已经知道的信息:如果您确实想对它们进行单独测试-我想也可以说这是对的-或者您有多个如果主要功能调用相同的子功能,那么实际上您可以像Jonas所说的那样运行子测试,或者编写一个包装该子功能测试的功能,并在每次主功能调用该子功能时运行该功能。据我所知,这还没有“黄金”规则。