首页 > 解决方案 > 如何在不重复的情况下测试功能?

问题描述

我有一个调用其他函数(子)的函数(主)。我已经为子函数编写了单元测试,现在想为主函数编写单元测试。问题是我如何测试主函数而不复制子函数的逻辑并在主函数测试中假设它们的逻辑(例如,在其中模拟对 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")
    }
}

标签: gotesting

解决方案


解决此问题的典型方法是仅测试公共接口的完整流程。如果您的(导出的)主函数调用您的子函数,那么子函数的测试发生在您的主函数的测试中。您不需要单独测试子功能,因为无论如何这些功能只能通过主功能来访问。如果主函数的测试通过了,则暗示子函数也通过了。

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


推荐阅读